diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 17bc7d0d..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,587 +0,0 @@ -# Changelog -## Master -[Work in progress](https://github.com/wpscanteam/wpscan/compare/2.9.4...master) - -## Version 2.9.4 -Released: 2018-06-15 - -* Updated dependencies and required ruby version -* Improved CLI output -* Only show readme.html output when wp <= 4.8 #1127 -* Cleanup README.md -* Fix bug "undefined method 'identifier' for nil:NilClass" #1149 -* Since WP 4.7 readme.html only shows major version #1152 -* Add checks for humans.txt and security.text (Thank you @g0tmi1k!) -* Add offline database update support (Thank you @g0tmi1k!) -* Check for API access and /wp-json/'s users output (Thank you @g0tmi1k!) -* Add RSS author information (Thank you @g0tmi1k!) -* Check HTTP status of each value in /robots.txt (Thank you @g0tmi1k!) -* Follow any redirections (e.g. http -> https) (Thank you @g0tmi1k!) -* Lots of other enhancements by @g0tmi1k & WPScan Team -* Database export file enumeration. - -WPScan Database Statistics: -* Total tracked wordpresses: 319 -* Total tracked plugins: 74896 -* Total tracked themes: 16666 -* Total vulnerable wordpresses: 305 -* Total vulnerable plugins: 1645 -* Total vulnerable themes: 286 -* Total wordpress vulnerabilities: 8327 -* Total plugin vulnerabilities: 2603 -* Total theme vulnerabilities: 352 - -## Version 2.9.3 -Released: 2017-07-19 - -* Updated dependencies and required ruby version -* Made some changes so wpscan works in ruby 2.4 -* Added a Gemfile.lock to lock all dependencies -* You can now pass a wordlist from stdin via "--wordlist -" -* Improved version detection regexes -* Added an optional paramter to --log to specify a filename - -WPScan Database Statistics: -* Total tracked wordpresses: 251 -* Total tracked plugins: 68818 -* Total tracked themes: 15132 -* Total vulnerable wordpresses: 243 -* Total vulnerable plugins: 1527 -* Total vulnerable themes: 280 -* Total wordpress vulnerabilities: 5263 -* Total plugin vulnerabilities: 2406 -* Total theme vulnerabilities: 349 - -## Version 2.9.2 -Released: 2016-11-15 - -* Fixed error when detecting plugins with UTF-8 characters -* Use all possible finders to verify a detected version -* Fix error when detecting a WordPress version not in our database -* Added some additional clarification on error messages -* Upgrade terminal-table gem -* Add --cache-dir option -* Add --disable-tls-checks options -* Improve/add additional plugin passive detections -* Remove scripts when calculating page hashes -* Many other small bug fixes. - -WPScan Database Statistics: -* Total tracked wordpresses: 194 -* Total tracked plugins: 63703 -* Total tracked themes: 13835 -* Total vulnerable wordpresses: 177 -* Total vulnerable plugins: 1382 -* Total vulnerable themes: 379 -* Total wordpress vulnerabilities: 2617 -* Total plugin vulnerabilities: 2190 -* Total theme vulnerabilities: 452 - -## Version 2.9.1 -Released: 2016-05-06 - -* Update to Ruby 2.3.1, drop older ruby support -* New data file location -* Added experimental Windows support -* Display WordPress metadata on the detected version -* Several small fixes - -WPScan Database Statistics: -* Total vulnerable versions: 156 -* Total vulnerable plugins: 1324 -* Total vulnerable themes: 376 -* Total version vulnerabilities: 1998 -* Total plugin vulnerabilities: 2057 -* Total theme vulnerabilities: 449 - -## Version 2.9 -Released: 2015-10-15 - -New -* GZIP Encoding in updater -* Adds --throttle option to throttle requests -* Uses new API and local database file structure -* Adds last updated and latest version to plugins and themes - -Removed -* ArchAssault from README -* APIv1 local databases - -General core -* Update to Ruby 2.2.3 -* Use yajl-ruby as JSON parser -* New dependancy for Ubuntu 14.04 (libgmp-dev) -* Use Travis container based infra and caching - -Fixed issues -* Fix #835 - Readme requests to wp root dir -* Fix #836 - Critical icon output twice when the site is not running WP -* Fix #839 - Terminal-table dependency is broken -* Fix #841 - error: undefined method `cells' for # -* Fix #852 - GZIP Encoding in updater -* Fix #853 - APIv2 integration -* Fix #858 - Detection FP -* Fix #873 - false positive "site has Must Use Plugins" - -WPScan Database Statistics: -* Total vulnerable versions: 132 -* Total vulnerable plugins: 1170 -* Total vulnerable themes: 368 -* Total version vulnerabilities: 1476 -* Total plugin vulnerabilities: 1913 -* Total theme vulnerabilities: 450 - -## Version 2.8 -Released: 2015-06-22 - -New -* Warn the user to update his DB files -* Added last db update to --version option (see #815) -* Add db checksum to verbose logging during update -* Option to hide banner -* Continue if user chooses not to update + db exists -* Don't update if user chooses default + no DBs exist -* Updates request timeout values to realistic ones (and in seconds) - -Removed -* Removed `Time.parse('2000-01-01')` expedient -* Removed unnecessary 'return' and '()' -* Removed debug output -* Removed wpstools - -General core -* Update to Ruby 2.2.2 -* Switch to mitre -* Install bundler gem README -* Switch from gnutls to openssl - -Fixed issues -* Fix #789 - Add blackarch to readme -* Fix #790 - Consider the target down after 30 requests timed out requests instead of 10 -* Fix #791 - Rogue character causing the scan of non-wordpress site to crash -* Fix #792 - Adds the HttpError exception -* Fix #795 - Remove GHOST warning -* Fix #796 - Do not swallow exit code -* Fix #797 - Increases the timeout values -* Fix #801 - Forces UTF-8 encoding when enumerating usernames -* Fix #803 - Increases default connect-timeout to 10s -* Fix #804 - Updates the Theme detection pattern -* Fix #816 - Ignores potential non version chars in theme version detection -* Fix #819 - Removes potential spaces in robots.txt entries - -WPScan Database Statistics: -* Total vulnerable versions: 98 -* Total vulnerable plugins: 1076 -* Total vulnerable themes: 361 -* Total version vulnerabilities: 1104 -* Total plugin vulnerabilities: 1763 -* Total theme vulnerabilities: 443 - -## Version 2.7 -Released: 2015-03-16 - -New -* Detects version in release date format -* Copyrights updated -* WP version detection from stylesheets -* New license -* Global HTTP request counter -* Add security-protection plugin detection -* Add GHOST warning if XMLRPC enabled -* Update databases from wpvulndb.com -* Enumerate usernames from WP <= 3.0 (thanks berotti3) - -Removed -* README.txt - -General core -* Update to Ruby 2.2.1 -* Update to Ruby 2.2.0 -* Add addressable gem -* Update Typhoeus gem to 0.7.0 -* IDN support: encode non-ascii domain names (thanks dctabuyz) -* Improve page hash calculation (thanks dctabuyz) -* Version detection regex improved - -Fixed issues -* Fix #745 - Plugin version pattern in readme.txt file not detected -* Fix #746 - Add a global counter for all active requests to server. -* Fix #747 - Add 'security-protection' plugin to wp_login_protection module -* Fix #753 - undefined method `round' for "10":String for request or connect timeouts -* Fix #760 - typhoeus issue (infinite loop) - -WPScan Database Statistics: -* Total vulnerable versions: 89 -* Total vulnerable plugins: 953 -* Total vulnerable themes: 329 -* Total version vulnerabilities: 1070 -* Total plugin vulnerabilities: 1451 -* Total theme vulnerabilities: 378 - -## Version 2.6 -Released: 2014-12-19 - -New -* Updates the readmes to reflect the new --usernames option -* Improves plugin/theme version detection by looking at the "Version:" -* Solution to avoid mandatory blank newline at the end of the wordlist -* Add check for valid credentials -* Add Sucuri sponsor to banner -* Add protocol to sucuri url in banner -* Add response code to proxy error output -* Add a statement about mandatory newlines at the end of list -* Give warning if default username 'admin' is still used -* License amendment to make it more clear about value added usage - -Removed -* remove malwares -* remove malware folder -* Removes the theme version check from the readme, unrealistic scenario - -General core -* Update to Ruby 2.1.5 and travis -* Prevent parent theme infinite loop -* Fixes the progressbar being overriden by next brute forcing attempts - -Fixed issues -* Fix UTF-8 encode on security db file download -* Fix #703 - Disable logging by default. Implement log option. -* Fix #705 - Installation instructions for Ubuntu < 14.04 apparently incomplete -* Fix #717 - Expand on readme.html finding output -* Fix #716 - Adds the --version in the help -* Fix #715 - Add new updating info to docs -* Fix #727 - WpItems detection: Perform the passive check and filter only vulnerable results at the end if required -* Fix #737 - Adds some readme files to check for plugin versions -* Fix #739 - Adds the --usernames option - -WPScan Database Statistics: -* Total vulnerable versions: 88 -* Total vulnerable plugins: 901 -* Total vulnerable themes: 313 -* Total version vulnerabilities: 1050 -* Total plugin vulnerabilities: 1355 -* Total theme vulnerabilities: 349 - -## Version 2.5.1 -Released: 2014-09-29 - -Fixes reference URL to WPVDB - -## Version 2.5 -Released: 2014-09-26 (@ BruCON 2014) - -New -* Exit program after --update -* Detect directory listing in upload folder -* Be more verbose when no version can be detected -* Added detection for Yoast Wordpress SEO plugin -* Also ensure to not process empty Location headers -* Ensures a nil location is not processed when enumerating usernames -* Fix #626 - Detect 'Must_Use_Plugins' -* better username extraction -* Add a --cookie option. Ref #485 -* Add a --no-color option -* Output: Give 'Fixed in' an informational tag -* Added ArchAssault distro - WPScan comes pre-installed with this distro -* Layout changes with new colors - -Removed -* Removes the source code updaters -* Removes the ListGenerator plugin from WPStools -* Removes all files from data/ - -General core -* Update docs to reflect new updating logic -* Little output change and coloring -* Adds a missing verbose output -* Re-build redirection url if begin with slash '/' -* Fixes the remove_conditional_comments function -* Ensures to give a string to Typhoeus -* Fix wpstools check-vuln-ref-urls -* Fix rspecs for new json -* Only output if different from style_url -* Add exception so 'ruby wpscan.rb http://domain.com' is detected -* Added make to Debian installation, which is needed in minimal installation. -* Add build-essentials requirement to Ubuntu > 14.04 -* Updated installation instr. for GNU/Linux Debian. -* Changes VersionCompare#is_newer_or_same? by lesser_or_equal? -* Fixes the location of the robots.txt check -* Updates the recommended ruby version -* Rspec 3.0 support -* Adds ruby 2.1.2 to Travis -* Updated ruby-progressbar to 1.5.0 - -WordPress Fingerprints -* Adds WP 4.0 fingerprints -* Adds WP 3.9.2, 3.8.4 & 3.7.4 fingerprints - Ref #652 -* Adds 3.9.1 fingerprints - -Fixed issues -* Fix #689 - Adds config file to check -* Fix #694 - Output Arrays -* Fix #693 - Adds pathname require statement -* Fix #657 - generate method -* Fix #685 - Potenial fix for 'marshal data too short' error -* Fix #686 - Adds specs for relative URI in Location headers -* Fix #435 - Update license -* Fix #674 - Improves the Plugins & Themes passive detection -* Fix #673 - Problem with the output -* Fix #661 - Don't hash directories named like a file -* Fix #653 - Fix for infinite loop in wpstools -* Fix #625 - Only parse styles when needed -* Fix #481 - Fix for Jetpack plugin false positive -* Fix #480 - Properly removes the colour sequence from log -* Fix #472 - WPScan stops after redirection if not WordPress website -* Fix #464 - Readmes updated to reflect recent changes about the config file & batch mode - -Vulnerabilities -* geoplaces4 also uses name GeoPlaces4beta -* Added metasploit module's -* Added some timthumb detections - -WPScan Database Statistics: -* Total vulnerable versions: 87 -* Total vulnerable plugins: 854 -* Total vulnerable themes: 303 -* Total version vulnerabilities: 752 -* Total plugin vulnerabilities: 1351 -* Total theme vulnerabilities: 345 - -## Version 2.4 -Released: 2014-04-17 - -New -* '--batch' switch option added - Fix #454 -* Add random-agent -* Added more CLI options -* Switch over to nist - Fix #301 -* New choice added when a redirection is detected - Fix #438 - -Removed -* Removed 'Total WordPress Sites in the World' counter from stats -* Old wpscan repo links removed - Fix #440 -* Fingerprinting Dev script removed -* Useless code removed - -General core -* Rspecs update -* Forcing Travis notify the team -* Ruby 2.1.1 added to Travis -* Equal output layout for interaction questions -* Only output error trace if verbose if enabled -* Memory improvements during wp-items enumerations -* Fixed broken link checker, fixed some broken links -* Couple more 404s fixed -* Themes & Plugins list updated - -WordPress Fingerprints -* WP 3.8.2 & 3.7.2 Fingerprints added - Fix #448 -* WP 3.8.3 & 3.7.3 fingerprints -* WP 3.9 fingerprints - -Fixed issues -* Fix #380 - Redirects in WP 3.6-3.0 -* Fix #413 - Check the version of the Timthumbs files found -* Fix #429 - Error WpScan Cache Browser -* Fix #431 - Version number comparison between '2.3.3' and '0.42b' -* Fix #439 - Detect if the target goes down during the scan -* Fix #451 - Do not rely only on files in wp-content for fingerprinting -* Fix #453 - Documentation or inplemention of option parameters -* Fix #455 - Fails with a message if the target returns a 403 during the wordpress check - -Vulnerabilities -* Update WordPress Vulnerabilities -* Fixed some duplicate vulnerabilities - -WPScan Database Statistics: -* Total vulnerable versions: 79; 1 is new -* Total vulnerable plugins: 748; 55 are new -* Total vulnerable themes: 292; 41 are new -* Total version vulnerabilities: 617; 326 are new -* Total plugin vulnerabilities: 1162; 146 are new -* Total theme vulnerabilities: 330; 47 are new - -## Version 2.3 -Released: 2014-02-11 - -New -* Brute forcing over https! -* Detect and output parent theme! -* Complete fingerprint script & hash search -* New spell checker! -* Added database modification dates in status report -* Added 'Total WordPress Sites in the World' statistics -* Added separator between Name and Version in Item -* Added a "Work in progress" URL in the CHANGELOG - -Removed -* Removed "Exiting!" sentence -* Removed Backtrack Linux. Not maintained anymore. - -General core -* Ruby 2.1.0 added to Travis -* Updated the version of WebMock required -* Better string concatenation in code (improves speed) -* Some modifications in the output of an item -* Output cosmetics -* rspec-mocks version constraint released -* Tabs replaced by spaces -* Rspecs update -* Indent code cleanup -* Themes & Plugins lists regenerated - -Vulnerabilities -* Update WordPress Vulnerabilities -* Disabled some fake reported vulnerabilities -* Fixed some duplicate vulnerabilities - -WPScan Database Statistics: -* Total vulnerable versions: 78; 2 are new -* Total vulnerable plugins: 693; 83 are new -* Total vulnerable themes: 251; 55 are new -* Total version vulnerabilities: 291 17 are new -* Total plugin vulnerabilities: 1016; 236 are new -* Total theme vulnerabilities: 283; 79 are new - -WordPress Fingerprints -* Better fingerprints -* WP 3.8.1 Fingerprinting -* WP 3.8 Fingerprinting - -Fixed issues -* Fix #404 - Brute forcing issue over https -* Fix #398 - Removed a fake vuln in WP Super Cache -* Fix #393 - sudo added to the bundle install cmd for Mac OSX -* Fix #228, #327 - Infinite loop when self-redirect -* Fix #201 - Incorrect Paramter Parsing when no url was supplied - -## Version 2.2 -Released: 2013-11-12 - -New -* Output the vulnerability fix if available -* Added 'WordPress Version Vulnerability' statistics -* Added Kali Linux on the list of pre-installed Linux distributions -* Added hosted wordpress detection. See issue #343. -* Add detection for all-in-one-seo-pack -* Use less memory when brute forcing with a large wordlist -* Memory Usage output -* Added cve tag to xml file -* Add documentation to readme -* Add --version switch -* Parse robots.txt -* Show twitter usernames -* Clean logfile on wpstools too -* Added pingback header -* Request_timeout and connect_timeout implemented -* Output interesting http-headers -* Kali Linux detection -* Ensure that brute forcing results are output even if an error occurs or the user exits -* Added debug output -* Fixed Version compare for issue #179 -* Added ruby-progressbar version to Gemfile -* Use the redirect_to parameter on bruteforce -* Readded "junk removal" from usernames before output -* Add license file -* Output the timthumb version if found -* New enumeration system -* More error details for XSD checks -* Added default wp-content dir detection, see Issue #141. -* Added checks for well formed xml - -Changed -* Trying a fix for Kali Linux -* Make a seperator between plugin name and vulnerability name -* It's WordPress, not Wordpress -* Changed wordpress.com scanning error to warning. See issue #343. -* Make output lines consistent -* Replace packetstormsecurity.org to packetstormsecurity.com -* Same URL syntax for all Packet Storm Security URL's -* Packet Storm Security URL's don't need the 'friendly part' of the URL. So it can be neglected. -* Use online documentation -* User prompt on same line -* Don't skip passwords that start with a hash. This is fairly common (see RockYou list for example). -* Updated Fedora install instructions as per Issue #92 -* Slight update to security plugin warning. Issue #212. -* Ruby-progressbar Gemfile version bump -* Fix error with the -U option (undefined method 'merge' for #WpTarget:) -* Banner artwork -* Fix hacks.rb conflict -* Handle when there are 2 headers of the same name -* Releasing the Typhoeus version constraint -* Amended Arch Linux install instructions. See issue #183. - -Updated -* Plugins & Themes updated -* Update README.md -* Updated documentation - -Removed -* Removed 'smileys' in output messages -* Removed 'for WordPress' and 'plugin' in title strings. -* Removed reference -* Removed useless code -* Removed duplicate vulnerabilities - -General core -* Code cleaning -* Fix typo's -* Clean up rspecs -* Themes & Plugins lists regenerated -* Rspecs update -* Code Factoring -* Added checks for old ruby. Otherwise there will be syntax errors - -Vulnerabilities -* Update WordPress Vulnerabilities -* Update timthumb due to Secunia #54801 -* Added WP vuln: 3.4 - 3.5.1 wp-admin/users.php FPD - -WPScan Database Statistics: -* Total vulnerable versions: 76; 4 are new -* Total vulnerable plugins: 610; 201 are new -* Total vulnerable themes: 196; 47 are new -* Total version vulnerabilities: 274; 53 are new -* Total plugin vulnerabilities: 780; 286 are new -* Total theme vulnerabilities: 204; 52 are new - -Add WP Fingerprints -* WP 3.7.1 Fingerprinting -* WP 3.7 Fingerprinting -* Ref #280 WP 3.6.1 fingerprint -* Added WP 3.6 advanced fingerprint hash. See Issue #255. -* Updated MD5 hash of WP 3.6 detection. See Issue #277. -* WP 3.5.2 Fingerprint -* Bug Fix : Wp 3.5 & 3.5.1 not detected from advanced fingerprinting. - -Fixed issues -* Fix #249 - [ERROR] "\xF1" on US-ASCII -* Fix #275 - [ERROR] "\xC3" on US-ASCII -* Fix #271 - Further Instructions added to the Mac Install -* Fix #266 - passive detection regex -* Fix #265 - remove base64 images before passive detection -* Fix #262 - [ERROR] bad component(expected absolute path component) -* Fix #260 - Fixes Travis Fail, due to rspec-mock v2.14.3 -* Fix #208 - Fixed vulnerable plugins still appear in the results -* Fix #245 - all theme enumeration error -* Fix #241 - Cant convert array to string -* Fix #232 - Crash while enumerating usernames -* Fix #223 - New wordpress urls for most popular plugins & themes -* Fix #177 - Passive Cache plugins detection (no spec) -* Fix #169 - False reports -* Fix #182 - Remove the progress-bar static length (120), and let it to automatic -* Fix #181 - Don't exit if no usernames found during a simple enumeration (but exit if a brute force is asked) -* Fix #200 - Log file not recording the list of username retireved -* Fix #164 - README.txt detection -* Fix #166 - ListGenerator using the old Browser#get method for full generation -* Fix #153 - Disable error trace when it's from the main script -* Fix #163 - in the proper way -* Fix #144 - Use cookie jar to prevent infinite redirections loop -* Fix #158 - Add the solution to 'no such file to load -- rubygems' in the README -* Fix #152 - invalid ssl_certificate - response code 0 -* Fix #147 - can't modify frozen string -* Fix #140 - xml_rpc_url in the body -* Fix #153 - No error trace when 'No argument supplied' - -## Version 2.1 -Released 2013-3-4 diff --git a/DISCLAIMER.md b/DISCLAIMER.md deleted file mode 100644 index 0d7199ab..00000000 --- a/DISCLAIMER.md +++ /dev/null @@ -1,2 +0,0 @@ -WPScan is not responsible for misuse or for any damage that you may cause! -You agree that you use this software at your own risk. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 4af7010b..00000000 --- a/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -FROM ruby:2.5-alpine -LABEL maintainer="WPScan Team " - -ARG BUNDLER_ARGS="--jobs=8 --without test" - -# Add a new user -RUN adduser -h /wpscan -g WPScan -D wpscan - -# Setup gems -RUN echo "gem: --no-ri --no-rdoc" > /etc/gemrc - -COPY Gemfile /wpscan -COPY Gemfile.lock /wpscan - -# Runtime dependencies -RUN apk add --no-cache libcurl procps && \ - # build dependencies - apk add --no-cache --virtual build-deps alpine-sdk ruby-dev libffi-dev zlib-dev && \ - bundle install --system --gemfile=/wpscan/Gemfile $BUNDLER_ARGS && \ - apk del --no-cache build-deps - -# Copy over data & set permissions -COPY . /wpscan -RUN chown -R wpscan:wpscan /wpscan - -# Switch directory -WORKDIR /wpscan - -# Switch users -USER wpscan - -# Update WPScan -RUN /wpscan/wpscan.rb --update --verbose --no-color - -# Run WPScan -ENTRYPOINT ["/wpscan/wpscan.rb"] -CMD ["--help"] diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 03bc4df5..00000000 --- a/Gemfile +++ /dev/null @@ -1,16 +0,0 @@ -source 'https://rubygems.org' - -gem 'addressable', '>=2.5.0' -gem 'nokogiri', '>=1.7.0.1' -gem 'ruby-progressbar', '>=1.8.1' -gem 'rubyzip', '>=1.2.1' -gem 'terminal-table', '>=1.6.0' -gem 'typhoeus', '>=1.1.2' -gem 'yajl-ruby', '>=1.3.0' # Better JSON parser regarding memory usage - -group :test do - gem 'webmock', '>=2.3.2' - gem 'simplecov', '>=0.13.0' - gem 'rspec', '>=3.5.0' - gem 'rspec-its', '>=1.2.0' -end diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index aeb6e493..00000000 --- a/Gemfile.lock +++ /dev/null @@ -1,71 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - addressable (2.5.2) - public_suffix (>= 2.0.2, < 4.0) - crack (0.4.3) - safe_yaml (~> 1.0.0) - diff-lcs (1.3) - docile (1.3.1) - ethon (0.11.0) - ffi (>= 1.3.0) - ffi (1.9.25) - hashdiff (0.3.7) - json (2.1.0) - mini_portile2 (2.3.0) - nokogiri (1.8.4) - mini_portile2 (~> 2.3.0) - public_suffix (3.0.2) - rspec (3.7.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-core (3.7.1) - rspec-support (~> 3.7.0) - rspec-expectations (3.7.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-its (1.2.0) - rspec-core (>= 3.0.0) - rspec-expectations (>= 3.0.0) - rspec-mocks (3.7.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-support (3.7.1) - ruby-progressbar (1.9.0) - rubyzip (1.2.1) - safe_yaml (1.0.4) - simplecov (0.16.1) - docile (~> 1.1) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.2) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) - typhoeus (1.3.0) - ethon (>= 0.9.0) - unicode-display_width (1.4.0) - webmock (3.4.2) - addressable (>= 2.3.6) - crack (>= 0.3.2) - hashdiff - yajl-ruby (1.4.0) - -PLATFORMS - ruby - -DEPENDENCIES - addressable (>= 2.5.0) - nokogiri (>= 1.7.0.1) - rspec (>= 3.5.0) - rspec-its (>= 1.2.0) - ruby-progressbar (>= 1.8.1) - rubyzip (>= 1.2.1) - simplecov (>= 0.13.0) - terminal-table (>= 1.6.0) - typhoeus (>= 1.1.2) - webmock (>= 2.3.2) - yajl-ruby (>= 1.3.0) - -BUNDLED WITH - 1.16.3 diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 4cf675c9..00000000 --- a/LICENSE +++ /dev/null @@ -1,74 +0,0 @@ -WPScan Public Source License - -The WPScan software (henceforth referred to simply as "WPScan") is dual-licensed - Copyright 2011-2018 WPScan Team. - -Cases that include commercialization of WPScan require a commercial, non-free license. Otherwise, WPScan can be used without charge under the terms set out below. - -1. Definitions - -1.1 “License” means this document. -1.2 “Contributor” means each individual or legal entity that creates, contributes to the creation of, or owns WPScan. -1.3 “WPScan Team” means WPScan’s core developers. - -2. Commercialization - -A commercial use is one intended for commercial advantage or monetary compensation. - -Example cases of commercialization are: - - - Using WPScan to provide commercial managed/Software-as-a-Service services. - - Distributing WPScan as a commercial product or as part of one. - - Using WPScan as a value added service/product. - -Example cases which do not require a commercial license, and thus fall under the terms set out below, include (but are not limited to): - - - Penetration testers (or penetration testing organizations) using WPScan as part of their assessment toolkit. - - Penetration Testing Linux Distributions including but not limited to Kali Linux, SamuraiWTF, BackBox Linux. - - Using WPScan to test your own systems. - - Any non-commercial use of WPScan. - -If you need to purchase a commercial license or are unsure whether you need to purchase a commercial license contact us - team@wpscan.org. - -We may grant commercial licenses at no monetary cost at our own discretion if the commercial usage is deemed by the WPScan Team to significantly benefit WPScan. - -Free-use Terms and Conditions; - -3. Redistribution - -Redistribution is permitted under the following conditions: - - - Unmodified License is provided with WPScan. - - Unmodified Copyright notices are provided with WPScan. - - Does not conflict with the commercialization clause. - -4. Copying - -Copying is permitted so long as it does not conflict with the Redistribution clause. - -5. Modification - -Modification is permitted so long as it does not conflict with the Redistribution clause. - -6. Contributions - -Any Contributions assume the Contributor grants the WPScan Team the unlimited, non-exclusive right to reuse, modify and relicense the Contributor's content. - -7. Support - -WPScan is provided under an AS-IS basis and without any support, updates or maintenance. Support, updates and maintenance may be given according to the sole discretion of the WPScan Team. - -8. Disclaimer of Warranty - -WPScan is provided under this License on an “as is” basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the WPScan is free of defects, merchantable, fit for a particular purpose or non-infringing. - -9. Limitation of Liability - -To the extent permitted under Law, WPScan is provided under an AS-IS basis. The WPScan Team shall never, and without any limit, be liable for any damage, cost, expense or any other payment incurred as a result of WPScan's actions, failure, bugs and/or any other interaction between WPScan and end-equipment, computers, other software or any 3rd party, end-equipment, computer or services. - -10. Disclaimer - -Running WPScan against websites without prior mutual consent may be illegal in your country. The WPScan Team accept no liability and are not responsible for any misuse or damage caused by WPScan. - -11. Trademark - -The "wpscan" term is a registered trademark. This License does not grant the use of the "wpscan" trademark or the use of the WPScan logo. diff --git a/README.md b/README.md deleted file mode 100644 index b3aa0129..00000000 --- a/README.md +++ /dev/null @@ -1,318 +0,0 @@ -![alt text](https://raw.githubusercontent.com/wpscanteam/wpscan/gh-pages/wpscan_logo_407x80.png "WPScan - WordPress Security Scanner") - -[![Build Status](https://travis-ci.org/wpscanteam/wpscan.svg?branch=master)](https://travis-ci.org/wpscanteam/wpscan) -[![Code Climate](https://img.shields.io/codeclimate/github/wpscanteam/wpscan.svg)](https://codeclimate.com/github/wpscanteam/wpscan) -[![Docker Pulls](https://img.shields.io/docker/pulls/wpscanteam/wpscan.svg)](https://hub.docker.com/r/wpscanteam/wpscan/) -[![Patreon Donate](https://img.shields.io/badge/patreon-donate-green.svg)](https://www.patreon.com/wpscan) - -![alt text](https://wpscan.org/images/tty.gif "WPScan Screen Recording") - -# LICENSE - -## WPScan Public Source License - -The WPScan software (henceforth referred to simply as "WPScan") is dual-licensed - Copyright 2011-2018 WPScan Team. - -Cases that include commercialization of WPScan require a commercial, non-free license. Otherwise, WPScan can be used without charge under the terms set out below. - -### 1. Definitions - -1.1 "License" means this document. - -1.2 "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns WPScan. - -1.3 "WPScan Team" means WPScan’s core developers, an updated list of whom can be found within the CREDITS file. - -### 2. Commercialization - -A commercial use is one intended for commercial advantage or monetary compensation. - -Example cases of commercialization are: - - - Using WPScan to provide commercial managed/Software-as-a-Service services. - - Distributing WPScan as a commercial product or as part of one. - - Using WPScan as a value added service/product. - -Example cases which do not require a commercial license, and thus fall under the terms set out below, include (but are not limited to): - - - Penetration testers (or penetration testing organizations) using WPScan as part of their assessment toolkit. - - Penetration Testing Linux Distributions including but not limited to Kali Linux, SamuraiWTF, BackBox Linux. - - Using WPScan to test your own systems. - - Any non-commercial use of WPScan. - -If you need to purchase a commercial license or are unsure whether you need to purchase a commercial license contact us - team@wpscan.org. - -We may grant commercial licenses at no monetary cost at our own discretion if the commercial usage is deemed by the WPScan Team to significantly benefit WPScan. - -Free-use Terms and Conditions; - -### 3. Redistribution - -Redistribution is permitted under the following conditions: - - - Unmodified License is provided with WPScan. - - Unmodified Copyright notices are provided with WPScan. - - Does not conflict with the commercialization clause. - -### 4. Copying - -Copying is permitted so long as it does not conflict with the Redistribution clause. - -### 5. Modification - -Modification is permitted so long as it does not conflict with the Redistribution clause. - -### 6. Contributions - -Any Contributions assume the Contributor grants the WPScan Team the unlimited, non-exclusive right to reuse, modify and relicense the Contributor's content. - -### 7. Support - -WPScan is provided under an AS-IS basis and without any support, updates or maintenance. Support, updates and maintenance may be given according to the sole discretion of the WPScan Team. - -### 8. Disclaimer of Warranty - -WPScan is provided under this License on an “as is” basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the WPScan is free of defects, merchantable, fit for a particular purpose or non-infringing. - -### 9. Limitation of Liability - -To the extent permitted under Law, WPScan is provided under an AS-IS basis. The WPScan Team shall never, and without any limit, be liable for any damage, cost, expense or any other payment incurred as a result of WPScan's actions, failure, bugs and/or any other interaction between WPScan and end-equipment, computers, other software or any 3rd party, end-equipment, computer or services. - -### 10. Disclaimer - -Running WPScan against websites without prior mutual consent may be illegal in your country. The WPScan Team accept no liability and are not responsible for any misuse or damage caused by WPScan. - -### 11. Trademark - -The "wpscan" term is a registered trademark. This License does not grant the use of the "wpscan" trademark or the use of the WPScan logo. - -# INSTALL - -WPScan comes pre-installed on the following Linux distributions: - -- [BackBox Linux](http://www.backbox.org/) -- [Kali Linux](http://www.kali.org/) -- [Pentoo](http://www.pentoo.ch/) -- [SamuraiWTF](http://samurai.inguardians.com/) -- [BlackArch](http://blackarch.org/) - -On macOS WPScan is packaged by [Homebrew](https://brew.sh/) as [`wpscan`](http://braumeister.org/formula/wpscan). - -Windows is not supported - -We suggest you use our official Docker image from https://hub.docker.com/r/wpscanteam/wpscan/ to avoid installation problems. - -# DOCKER -## Install Docker -[https://docs.docker.com/engine/installation/](https://docs.docker.com/engine/installation/) - -## Get the image -Pull the repo with `docker pull wpscanteam/wpscan` - -## Start WPScan - -``` -docker run -it --rm wpscanteam/wpscan -u https://yourblog.com [options] -``` - -For the available Options, please see https://github.com/wpscanteam/wpscan#wpscan-arguments - -If you run the git version of wpscan we included some binstubs in ./bin for easier start of wpscan. - -## Examples - -Mount a local wordlist to the docker container and start a bruteforce attack for user admin - -``` -docker run -it --rm -v ~/wordlists:/wordlists wpscanteam/wpscan --url https://yourblog.com --wordlist /wordlists/crackstation.txt --username admin -``` - -(This mounts the host directory `~/wordlists` to the container in the path `/wordlists`) - -Use logfile option -``` -# the file must exist prior to starting the container, otherwise docker will create a directory with the filename -touch ~/FILENAME -docker run -it --rm -v ~/FILENAME:/wpscan/output.txt wpscanteam/wpscan --url https://yourblog.com --log /wpscan/output.txt -``` - -Published on https://hub.docker.com/r/wpscanteam/wpscan/ - -# Manual install - -## Prerequisites - -- Ruby >= 2.1.9 - Recommended: 2.5.1 -- Curl >= 7.21 - Recommended: latest - FYI the 7.29 has a segfault -- RubyGems - Recommended: latest -- Git - -### Installing dependencies on Ubuntu - - sudo apt-get install libcurl4-openssl-dev libxml2 libxml2-dev libxslt1-dev ruby-dev build-essential libgmp-dev zlib1g-dev - -### Installing dependencies on Debian - - sudo apt-get install gcc git ruby ruby-dev libcurl4-openssl-dev make zlib1g-dev - -### Installing dependencies on Fedora - - sudo dnf install gcc ruby-devel libxml2 libxml2-devel libxslt libxslt-devel libcurl-devel patch rpm-build - -### Installing dependencies on Arch Linux - - pacman -Syu ruby - pacman -Syu libyaml - -### Installing dependencies on macOS - -Apple Xcode, Command Line Tools and the libffi are needed (to be able to install the FFI gem), See [http://stackoverflow.com/questions/17775115/cant-setup-ruby-environment-installing-fii-gem-error](http://stackoverflow.com/questions/17775115/cant-setup-ruby-environment-installing-fii-gem-error) - -## Installing with RVM (recommended when doing a manual install) - -If you are using GNOME Terminal, there are some steps required before executing the commands. See here for more information: -https://rvm.io/integration/gnome-terminal#integrating-rvm-with-gnome-terminal - - # Install all prerequisites for your OS (look above) - cd ~ - curl -sSL https://rvm.io/mpapis.asc | gpg --import - - curl -sSL https://get.rvm.io | bash -s stable - source ~/.rvm/scripts/rvm - echo "source ~/.rvm/scripts/rvm" >> ~/.bashrc - rvm install 2.5.1 - rvm use 2.5.1 --default - echo "gem: --no-ri --no-rdoc" > ~/.gemrc - git clone https://github.com/wpscanteam/wpscan.git - cd wpscan - gem install bundler - bundle install --without test - -## Installing manually (not recommended) - - git clone https://github.com/wpscanteam/wpscan.git - cd wpscan - sudo gem install bundler && bundle install --without test - -# KNOWN ISSUES - - - no such file to load -- rubygems - - ```update-alternatives --config ruby``` - - And select your ruby version - - See [https://github.com/wpscanteam/wpscan/issues/148](https://github.com/wpscanteam/wpscan/issues/148) - -# WPSCAN ARGUMENTS - - --update Update the database to the latest version. - --url | -u The WordPress URL/domain to scan. - --force | -f Forces WPScan to not check if the remote site is running WordPress. - --enumerate | -e [option(s)] Enumeration. - option : - u usernames from id 1 to 10 - u[10-20] usernames from id 10 to 20 (you must write [] chars) - p plugins - vp only vulnerable plugins - ap all plugins (can take a long time) - tt timthumbs - t themes - vt only vulnerable themes - at all themes (can take a long time) - Multiple values are allowed : "-e tt,p" will enumerate timthumbs and plugins - If no option is supplied, the default is "vt,tt,u,vp" - - --exclude-content-based "" - Used with the enumeration option, will exclude all occurrences based on the regexp or string supplied. - You do not need to provide the regexp delimiters, but you must write the quotes (simple or double). - --config-file | -c Use the specified config file, see the example.conf.json. - --user-agent | -a Use the specified User-Agent. - --cookie String to read cookies from. - --random-agent | -r Use a random User-Agent. - --follow-redirection If the target url has a redirection, it will be followed without asking if you wanted to do so or not - --batch Never ask for user input, use the default behaviour. - --no-color Do not use colors in the output. - --log [filename] Creates a log.txt file with WPScan's output if no filename is supplied. Otherwise the filename is used for logging. - --no-banner Prevents the WPScan banner from being displayed. - --disable-accept-header Prevents WPScan sending the Accept HTTP header. - --disable-referer Prevents setting the Referer header. - --disable-tls-checks Disables SSL/TLS certificate verification. - --wp-content-dir WPScan try to find the content directory (ie wp-content) by scanning the index page, however you can specify it. - Subdirectories are allowed. - --wp-plugins-dir Same thing than --wp-content-dir but for the plugins directory. - If not supplied, WPScan will use wp-content-dir/plugins. Subdirectories are allowed - --proxy <[protocol://]host:port> Supply a proxy. HTTP, SOCKS4 SOCKS4A and SOCKS5 are supported. - If no protocol is given (format host:port), HTTP will be used. - --proxy-auth Supply the proxy login credentials. - --basic-auth Set the HTTP Basic authentication. - --wordlist | -w Supply a wordlist for the password brute forcer. - If the "-" option is supplied, the wordlist is expected via STDIN. - --username | -U Only brute force the supplied username. - --usernames Only brute force the usernames from the file. - --cache-dir Set the cache directory. - --cache-ttl Typhoeus cache TTL. - --request-timeout Request Timeout. - --connect-timeout Connect Timeout. - --threads | -t The number of threads to use when multi-threading requests. - --throttle Milliseconds to wait before doing another web request. If used, the --threads should be set to 1. - --help | -h This help screen. - --verbose | -v Verbose output. - --version Output the current version and exit. - -# WPSCAN EXAMPLES - -Do 'non-intrusive' checks... - -```ruby wpscan.rb --url www.example.com``` - -Do wordlist password brute force on enumerated users using 50 threads... - -```ruby wpscan.rb --url www.example.com --wordlist darkc0de.lst --threads 50``` - -Do wordlist password brute force on enumerated users using STDIN as the wordlist... - -```crunch 5 13 -f charset.lst mixalpha | ruby wpscan.rb --url www.example.com --wordlist -``` - -Do wordlist password brute force on the 'admin' username only... - -```ruby wpscan.rb --url www.example.com --wordlist darkc0de.lst --username admin``` - -Enumerate installed plugins... - -```ruby wpscan.rb --url www.example.com --enumerate p``` - -Run all enumeration tools... - -```ruby wpscan.rb --url www.example.com --enumerate``` - -Use custom content directory... - -```ruby wpscan.rb -u www.example.com --wp-content-dir custom-content``` - -Update WPScan's databases... - -```ruby wpscan.rb --update``` - -Debug output... - -```ruby wpscan.rb --url www.example.com --debug-output 2>debug.log``` - -# PROJECT HOME - -[http://www.wpscan.org](http://www.wpscan.org) - -# VULNERABILITY DATABASE - -[https://wpvulndb.com](https://wpvulndb.com) - -# GIT REPOSITORY - -[https://github.com/wpscanteam/wpscan](https://github.com/wpscanteam/wpscan) - -# ISSUES - -[https://github.com/wpscanteam/wpscan/issues](https://github.com/wpscanteam/wpscan/issues) - -# DEVELOPER DOCUMENTATION - -[http://rdoc.info/github/wpscanteam/wpscan/frames](http://rdoc.info/github/wpscanteam/wpscan/frames) diff --git a/bin/rspec b/bin/rspec deleted file mode 100755 index d8614a43..00000000 --- a/bin/rspec +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -cd $DIR/../ -# always rebuild and include all GEMs -docker build --build-arg "BUNDLER_ARGS=--jobs=8" -t wpscan:rspec . -# update all gems (this updates Gemfile.lock on the host) -# this also needs some build dependencies -docker run --rm -u root -v $DIR/../Gemfile.lock:/wpscan/Gemfile.lock --entrypoint "" wpscan:rspec sh -c 'apk add --no-cache alpine-sdk ruby-dev libffi-dev zlib-dev && bundle update' -# rebuild image with latest GEMs -docker build --build-arg "BUNDLER_ARGS=--jobs=8" -t wpscan:rspec . -# run spec -docker run --rm -v $DIR/../:/wpscan --entrypoint "" wpscan:rspec rspec - diff --git a/bin/update_gems b/bin/update_gems deleted file mode 100755 index 85749b18..00000000 --- a/bin/update_gems +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -cd $DIR/../ -docker run --rm -v "$DIR/../":/usr/src/app -w /usr/src/app ruby:2.5-alpine /bin/sh -c "gem install bundler; bundle lock --update" diff --git a/bin/wpscan b/bin/wpscan deleted file mode 100755 index 59a68c5c..00000000 --- a/bin/wpscan +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -cd $DIR/../ -docker build -q -t wpscan:git . -docker run -it --rm wpscan:git "$@" - diff --git a/bin/wpscan-dev b/bin/wpscan-dev deleted file mode 100755 index 4da39084..00000000 --- a/bin/wpscan-dev +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -cd $DIR/../ -if [[ -n "$WPSCAN_BUILD" ]]; then - docker build -q -t wpscan:git . -fi -docker run -it --rm -v $DIR/../:/wpscan wpscan:git "$@" - diff --git a/data.zip b/data.zip deleted file mode 100644 index ecea07bf..00000000 Binary files a/data.zip and /dev/null differ diff --git a/dev/pre-commit-hook.rb b/dev/pre-commit-hook.rb deleted file mode 100755 index 5da0c583..00000000 --- a/dev/pre-commit-hook.rb +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env ruby - -# from the top level dir: -# ln -sf ../../dev/pre-commit-hook.rb .git/hooks/pre-commit - -require 'pty' -html_path = 'rspec_results.html' - -begin - PTY.spawn( "rspec spec --format h > #{html_path}" ) do |stdin, stdout, pid| - begin - stdin.each { |line| print line } - rescue Errno::EIO => e - puts "Error: #{e.to.s}" - return 1 - end - end -rescue PTY::ChildExited - puts 'Child process exit!' -end - -# find out if there were any errors -html = open(html_path).read -examples = html.match(/(\d+) examples/)[0].to_i rescue 0 -errors = html.match(/(\d+) errors/)[0].to_i rescue 0 -if errors == 0 - errors = html.match(/(\d+) failure/)[0].to_i rescue 0 -end -pending = html.match(/(\d+) pending/)[0].to_i rescue 0 - -if errors.zero? - puts "0 failed! #{examples} run, #{pending} pending" - sleep 1 - exit 0 -else - puts "\aCOMMIT FAILED!!" - puts "View your rspec results at #{File.expand_path(html_path)}" - puts - puts "#{errors} failed! #{examples} run, #{pending} pending" - exit 1 -end diff --git a/dev/stats.rb b/dev/stats.rb deleted file mode 100755 index f7183599..00000000 --- a/dev/stats.rb +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env ruby -# encoding: UTF-8 - -require File.expand_path(File.join(__dir__, '..', 'lib', 'wpscan', 'wpscan_helper')) - -wordpress_json = json(WORDPRESSES_FILE) -plugins_json = json(PLUGINS_FILE) -themes_json = json(THEMES_FILE) - -puts 'WPScan Database Statistics:' -puts "* Total tracked wordpresses: #{wordpress_json.count}" -puts "* Total tracked plugins: #{plugins_json.count}" -puts "* Total tracked themes: #{themes_json.count}" -puts "* Total vulnerable wordpresses: #{wordpress_json.select { |item| !wordpress_json[item]['vulnerabilities'].empty? }.count}" -puts "* Total vulnerable plugins: #{plugins_json.select { |item| !plugins_json[item]['vulnerabilities'].empty? }.count}" -puts "* Total vulnerable themes: #{themes_json.select { |item| !themes_json[item]['vulnerabilities'].empty? }.count}" -puts "* Total wordpress vulnerabilities: #{wordpress_json.map {|k,v| v['vulnerabilities'].count}.inject(:+)}" -puts "* Total plugin vulnerabilities: #{plugins_json.map {|k,v| v['vulnerabilities'].count}.inject(:+)}" -puts "* Total theme vulnerabilities: #{themes_json.map {|k,v| v['vulnerabilities'].count}.inject(:+)}" diff --git a/example.conf.json b/example.conf.json deleted file mode 100644 index a4533544..00000000 --- a/example.conf.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0", - - /* Uncomment the "proxy" line to use the proxy - SOCKS proxies (4, 4A, 5) are supported, ie : "proxy": "socks5://127.0.0.1:9000" - If you do not specify the protocol, http will be used - */ - //"proxy": "127.0.0.1:3128", - //"proxy_auth": "username:password", - - "cache_ttl": 600, // 10 minutes, at this time the cache is cleaned before each scan. If this value is set to 0, the cache will be disabled - - "request_timeout": 60, // 1min - - "connect_timeout": 10, // 10s - - "max_threads": 20 -} diff --git a/lib/common/browser.rb b/lib/common/browser.rb deleted file mode 100644 index 8f595acf..00000000 --- a/lib/common/browser.rb +++ /dev/null @@ -1,204 +0,0 @@ -# encoding: UTF-8 - -require 'common/typhoeus_cache' -require 'common/browser/actions' -require 'common/browser/options' - -class Browser - extend Browser::Actions - include Browser::Options - - OPTIONS = [ - :basic_auth, - :cache_ttl, - :max_threads, - :user_agent, - :proxy, - :proxy_auth, - :request_timeout, - :connect_timeout, - :cookie, - :throttle, - :disable_accept_header, - :disable_referer, - :disable_tls_checks - ] - - @@instance = nil - - attr_reader :hydra, :cache_dir - - attr_accessor :referer, :cookie, :vhost - - # @param [ Hash ] options - # - # @return [ Browser ] - def initialize(options = {}) - @cache_dir = options[:cache_dir] || CACHE_DIR + '/browser' - - # sets browser defaults - browser_defaults - # load config file - conf = options[:config_file] - load_config(conf) if conf - # overrides defaults with user supplied values (overwrite values from config) - override_config(options) - - unless @hydra - @hydra = Typhoeus::Hydra.new(max_concurrency: self.max_threads) - end - - @cache = TyphoeusCache.new(@cache_dir) - @cache.clean - - Typhoeus::Config.cache = @cache - end - - private_class_method :new - - # @param [ Hash ] options - # - # @return [ Browser ] - def self.instance(options = {}) - unless @@instance - @@instance = new(options) - end - @@instance - end - - def self.reset - @@instance = nil - end - - # Override for setting the User-Agent - # @param [ String ] user_agent - def user_agent=(user_agent) - Typhoeus::Config.user_agent = user_agent - end - - # - # sets browser default values - # - def browser_defaults - Typhoeus::Config.user_agent = "WPScan v#{WPSCAN_VERSION} (http://wpscan.org)" - @max_threads = 20 - # 10 minutes, at this time the cache is cleaned before each scan. - # If this value is set to 0, the cache will be disabled - @cache_ttl = 600 - @request_timeout = 60 # 60s - @connect_timeout = 10 # 10s - @throttle = 0 - end - - # - # If an option was set but is not in the new config_file - # it's value is kept - # - # @param [ String ] config_file - # - # @return [ void ] - def load_config(config_file = nil) - if File.symlink?(config_file) - raise '[ERROR] Config file is a symlink.' - else - data = JSON.parse(File.read(config_file)) - end - - OPTIONS.each do |option| - option_name = option.to_s - unless data[option_name].nil? - self.send(:"#{option_name}=", data[option_name]) - end - end - end - - # @param [ String ] url - # @param [ Hash ] params - # - # @return [ Typhoeus::Request ] - def forge_request(url, params = {}) - Typhoeus::Request.new(url, merge_request_params(params)) - end - - # @param [ Hash ] params - # - # @return [ Hash ] - def merge_request_params(params = {}) - if @proxy - params.merge!(proxy: @proxy) - params.merge!(proxyuserpwd: @proxy_auth) if @proxy_auth - end - - if @basic_auth - params = Browser.append_params_header_field( - params, - 'Authorization', - @basic_auth - ) - end - - if vhost - params = Browser.append_params_header_field( - params, - 'Host', - vhost - ) - end - - params.merge!(referer: referer) - params.merge!(timeout: @request_timeout) if @request_timeout && !params.key?(:timeout) - params.merge!(connecttimeout: @connect_timeout) if @connect_timeout && !params.key?(:connecttimeout) - - # Used to enable the cache system if :cache_ttl > 0 - params.merge!(cache_ttl: @cache_ttl) unless params.key?(:cache_ttl) - - # Prevent infinite self redirection - params.merge!(maxredirs: 3) unless params.key?(:maxredirs) - - # Disable SSL-Certificate checks - if @disable_tls_checks - # Cert validity check - params.merge!(ssl_verifypeer: 0) unless params.key?(:ssl_verifypeer) - # Cert hostname check - params.merge!(ssl_verifyhost: 0) unless params.key?(:ssl_verifyhost) - end - - params.merge!(cookiejar: @cache_dir + '/cookie-jar') - params.merge!(cookiefile: @cache_dir + '/cookie-jar') - params.merge!(cookie: @cookie) if @cookie - params = Browser.remove_params_header_field(params, 'Accept') if @disable_accept_header - params = Browser.remove_params_header_field(params, 'Referer') if @disable_referer - - params - end - - private - - # @param [ Hash ] params - # @param [ String ] field - # @param [ Mixed ] field_value - # - # @return [ Array ] - def self.append_params_header_field(params = {}, field, field_value) - if !params.has_key?(:headers) - params = params.merge(:headers => { field => field_value }) - elsif !params[:headers].has_key?(field) - params[:headers][field] = field_value - end - params - end - - # @param [ Hash ] params - # @param [ String ] field - # @param [ Mixed ] field_value - # - # @return [ Array ] - def self.remove_params_header_field(params = {}, field) - if !params.has_key?(:headers) - params = params.merge(:headers => { field => nil }) - elsif !params[:headers].has_key?(field) - params[:headers][field] = nil - end - params - end -end diff --git a/lib/common/browser/actions.rb b/lib/common/browser/actions.rb deleted file mode 100644 index 13d4f158..00000000 --- a/lib/common/browser/actions.rb +++ /dev/null @@ -1,51 +0,0 @@ -# encoding: UTF-8 - -class Browser - module Actions - - # @param [ String ] url - # @param [ Hash ] params - # - # @return [ Typhoeus::Response ] - def get(url, params = {}) - process(url, params.merge(method: :get)) - end - - # @param [ String ] url - # @param [ Hash ] params - # - # @return [ Typhoeus::Response ] - def post(url, params = {}) - process(url, params.merge(method: :post)) - end - - # @param [ String ] url - # @param [ Hash ] params - # - # @return [ Typhoeus::Response ] - def head(url, params = {}) - process(url, params.merge(method: :head)) - end - - # @param [ String ] url - # @param [ Hash ] params - # - # @return [ Typhoeus::Response ] - def get_and_follow_location(url, params = {}) - params[:maxredirs] ||= 2 - - get(url, params.merge(followlocation: true)) - end - - protected - - # @param [ String ] url - # @param [ Hash ] params - # - # @return [ Typhoeus::Response ] - def process(url, params) - Typhoeus::Request.new(url, Browser.instance.merge_request_params(params)).run - end - - end -end diff --git a/lib/common/browser/options.rb b/lib/common/browser/options.rb deleted file mode 100644 index 84641b2a..00000000 --- a/lib/common/browser/options.rb +++ /dev/null @@ -1,122 +0,0 @@ -# encoding: UTF-8 - -class Browser - module Options - - attr_accessor :request_timeout, :connect_timeout, :user_agent, :disable_accept_header, :disable_referer, :disable_tls_checks - attr_reader :basic_auth, :cache_ttl, :proxy, :proxy_auth, :throttle - - # Sets the Basic Authentification credentials - # Accepted format: - # login:password - # Basic base_64_encoded - # - # @param [ String ] auth - # - # @return [ void ] - def basic_auth=(auth) - if auth.index(':') - @basic_auth = "Basic #{Base64.encode64(auth).chomp}" - elsif auth =~ /\ABasic [a-zA-Z0-9=]+\z/ - @basic_auth = auth - else - raise "Invalid basic authentication format, \"login:password\" or \"Basic base_64_encoded\" expected. Your input: #{auth}" - end - end - - def cache_ttl=(ttl) - @cache_ttl = ttl.to_i - end - - # @return [ Integer ] - def max_threads - @max_threads || 1 - end - - def max_threads=(threads) - if threads.is_a?(Integer) && threads > 0 - @max_threads = threads - @hydra = Typhoeus::Hydra.new(max_concurrency: threads) - else - raise 'max_threads must be an Integer > 0' - end - end - - # Sets the proxy - # Accepted format: - # [protocol://]host:post - # - # Supported protocols: - # Depends on the curl protocols, See curl --version - # - # @param [ String ] proxy - # - # @return [ void ] - def proxy=(proxy) - if proxy.index(':') - @proxy = proxy - else - raise 'Invalid proxy format. Should be [protocol://]host:port.' - end - end - - # Sets the proxy credentials - # Accepted format: - # username:password - # { proxy_username: username, :proxy_password: password } - # - # @param [ String ] auth - # - # @return [ void ] - def proxy_auth=(auth) - unless auth.nil? - if auth.is_a?(Hash) && auth.include?(:proxy_username) && auth.include?(:proxy_password) - @proxy_auth = auth[:proxy_username] + ':' + auth[:proxy_password] - elsif auth.is_a?(String) && auth.index(':') != nil - @proxy_auth = auth - else - raise invalid_proxy_auth_format - end - end - end - - # Sets the request timeout - # @param [ Integer ] timeout Timeout in ms - # - # @return [ void ] - def request_timeout=(timeout) - @request_timeout = timeout.to_i - end - - # Sets the connect timeout - # @param [ Integer ] timeout Timeout in ms - # - # @return [ void ] - def connect_timeout=(timeout) - @connect_timeout = timeout.to_i - end - - # @param [ String, Integer ] throttle - def throttle=(throttle) - @throttle = throttle.to_i.abs / 1000.0 - end - - protected - - def invalid_proxy_auth_format - 'Invalid proxy auth format, expected username:password or {proxy_username: username, proxy_password: password}' - end - - # Override with the options if they are set - # @param [ Hash ] options - # - # @return [ void ] - def override_config(options = {}) - options.each do |option, value| - if value != nil and OPTIONS.include?(option) - self.send(:"#{option}=", value) - end - end - end - end -end diff --git a/lib/common/cache_file_store.rb b/lib/common/cache_file_store.rb deleted file mode 100644 index 98c0f331..00000000 --- a/lib/common/cache_file_store.rb +++ /dev/null @@ -1,78 +0,0 @@ -# encoding: UTF-8 - -# -# => @todo take consideration of the cache_timeout : -# -> create 2 files per key : one for the data storage (key.store ?) -# and the other for the cache timeout (key.expiration, key.timeout ?) -# or 1 file for all timeouts ? -# -> 2 dirs : 1 for storage, the other for cache_timeout ? -# - -require 'yaml' -require 'fileutils' - -class CacheFileStore - attr_reader :storage_path, :cache_dir, :serializer - - # The serializer must have the 2 methods .load and .dump - # (Marshal and YAML have them) - # YAML is Human Readable, contrary to Marshal which store in a binary format - # Marshal does not need any "require" - def initialize(storage_path, serializer = Marshal) - @cache_dir = File.expand_path(storage_path) - @storage_path = File.expand_path(File.join(storage_path, storage_dir)) - @serializer = serializer - - unless Dir.exist?(@storage_path) - FileUtils.mkdir_p(@storage_path) - end - - unless Pathname.new(@storage_path).writable? - fail "#{@storage_path} is not writable" - end - end - - def clean - # clean old directories - Dir[File.join(@cache_dir, '*')].each do |f| - if File.directory?(f) - # delete directory if create time is older than 4 hours - FileUtils.rm_rf(f) if File.mtime(f) < (Time.now - (60*240)) - else - File.delete(f) unless File.symlink?(f) - end - end - end - - def read_entry(key) - begin - @serializer.load(File.read(get_entry_file_path(key))) - rescue - nil - end - end - - def write_entry(key, data_to_store, cache_ttl) - if cache_ttl && cache_ttl > 0 - File.open(get_entry_file_path(key), 'w') do |f| - begin - f.write(@serializer.dump(data_to_store)) - rescue - nil # spec fix for "can't dump hash with default proc" when stub_request with response headers - end - end - end - end - - def get_entry_file_path(key) - File::join(@storage_path, key) - end - - def storage_dir - time = Time.now - random = (0...8).map { (65 + rand(26)).chr }.join - - Digest::MD5.hexdigest("#{time}#{random}") - end - -end diff --git a/lib/common/collections/vulnerabilities.rb b/lib/common/collections/vulnerabilities.rb deleted file mode 100644 index a26868eb..00000000 --- a/lib/common/collections/vulnerabilities.rb +++ /dev/null @@ -1,8 +0,0 @@ -# encoding: UTF-8 - -require 'common/collections/vulnerabilities/output' - -class Vulnerabilities < Array - include Vulnerabilities::Output - -end diff --git a/lib/common/collections/vulnerabilities/output.rb b/lib/common/collections/vulnerabilities/output.rb deleted file mode 100644 index 632aed88..00000000 --- a/lib/common/collections/vulnerabilities/output.rb +++ /dev/null @@ -1,13 +0,0 @@ -# encoding: UTF-8 - -class Vulnerabilities < Array - module Output - - def output(verbose = false) - self.each do |v| - v.output(verbose) - end - end - - end -end diff --git a/lib/common/collections/wp_items.rb b/lib/common/collections/wp_items.rb deleted file mode 100644 index e7a24531..00000000 --- a/lib/common/collections/wp_items.rb +++ /dev/null @@ -1,75 +0,0 @@ -# encoding: UTF-8 - -require 'common/collections/wp_items/detectable' -require 'common/collections/wp_items/output' - -class WpItems < Array - extend WpItems::Detectable - include WpItems::Output - - attr_accessor :wp_target - - # @param [ WpTarget ] wp_target - def initialize(wp_target = nil) - self.wp_target = wp_target - end - - # @param [String] args - # - # @return [ void ] - def add(*args) - index = 0 - - until args[index].nil? - arg = args[index] - - if arg.is_a?(String) - if (next_arg = args[index + 1]).is_a?(Hash) - item = create_item(arg, next_arg) - index += 1 - else - item = create_item(arg) - end - elsif arg.is_a?(Item) - item = arg - else - raise 'Invalid arguments' - end - - self << item - index += 1 - end - end - - # @param [ String ] name - # @param [ Hash ] attrs - # - # @return [ WpItem ] - def create_item(name, attrs = {}) - raise 'wp_target must be set' unless wp_target - - item_class.new( - wp_target.uri, - attrs.merge( - name: name, - wp_content_dir: wp_target.wp_content_dir, - wp_plugins_dir: wp_target.wp_plugins_dir - ) { |key, oldval, newval| oldval } - ) - end - - # @param [ WpItems ] other - # - # @return [ self ] - def +(other) - other.each { |item| self << item } - self - end - - protected - - # @return [ Class ] - def item_class - Object.const_get(self.class.to_s.gsub(/.$/, '')) - end -end diff --git a/lib/common/collections/wp_items/detectable.rb b/lib/common/collections/wp_items/detectable.rb deleted file mode 100644 index bca5cd6c..00000000 --- a/lib/common/collections/wp_items/detectable.rb +++ /dev/null @@ -1,240 +0,0 @@ -# encoding: UTF-8 - -class WpItems < Array - module Detectable - - attr_reader :vulns_file, :item_xpath - - # @param [ WpTarget ] wp_target - # @param [ Hash ] options - # @option options [ Boolean ] :show_progression Whether or not output the progress bar - # @option options [ Boolean ] :only_vulnerable Only check for vulnerable items - # @option options [ String ] :exclude_content - # - # @return [ WpItems ] - def aggressive_detection(wp_target, options = {}) - browser = Browser.instance - hydra = browser.hydra - targets = targets_items(wp_target, options) - progress_bar = progress_bar(targets.size, options) - queue_count = 0 - exist_options = { - error_404_hash: wp_target.error_404_hash, - homepage_hash: wp_target.homepage_hash, - exclude_content: options[:exclude_content] ? %r{#{options[:exclude_content]}} : nil - } - results = passive_detection(wp_target, options) - - targets.each do |target_item| - request = browser.forge_request(target_item.url, request_params) - - request.on_complete do |response| - progress_bar.progress += 1 if options[:show_progression] - - if target_item.exists?(exist_options, response) - results << target_item unless results.include?(target_item) - end - end - - hydra.queue(request) - queue_count += 1 - - if queue_count >= browser.max_threads - hydra.run - queue_count = 0 - puts "Sent #{browser.max_threads} requests ..." if options[:verbose] - end - end - - # run the remaining requests - hydra.run - - results.select!(&:vulnerable?) if options[:type] == :vulnerable - results.sort! - - results # can't just return results.sort as it would return an array, and we want a WpItems - end - - # @param [ Integer ] targets_size - # @param [ Hash ] options - # - # @return [ ProgressBar ] - # :nocov: - def progress_bar(targets_size, options) - if options[:show_progression] - ProgressBar.create( - format: '%t %a <%B> (%c / %C) %P%% %e', - title: ' ', # Used to craete a left margin - total: targets_size - ) - end - end - # :nocov: - - # @param [ WpTarget ] wp_target - # @param [ Hash ] options - # - # @return [ WpItems ] - def passive_detection(wp_target, options = {}) - results = new(wp_target) - # improves speed - body = remove_base64_images_from_html(Browser.get(wp_target.url).body) - page = Nokogiri::HTML(body) - names = [] - - page.css('link,script,style').each do |tag| - %w(href src).each do |attribute| - attr_value = tag.attribute(attribute).to_s - next unless attr_value - - names << Regexp.last_match[1] if attr_value.match(attribute_pattern(wp_target)) - end - - next unless tag.name == 'script' || tag.name == 'style' - - code = tag.text.to_s - next if code.empty? - - if !code.valid_encoding? - code = code.encode('UTF-16be', :invalid => :replace, :replace => '?').encode('UTF-8') - end - - code.scan(code_pattern(wp_target)).flatten.uniq.each do |item_name| - names << item_name - end - end - - names.uniq.each { |name| results.add(name) } - - results.sort! - results - end - - protected - - # @param [ WpTarget ] wp_target - # - # @return [ Regex ] - def item_pattern(wp_target) - type = to_s.gsub(/Wp/, '').downcase - wp_content_dir = wp_target.wp_content_dir - wp_content_url = wp_target.uri.merge(wp_content_dir).to_s - - url = wp_content_url.gsub(%r{\A(?:http|https)://}, '(?:https?:)?//').gsub('/', '\\\\\?\/') - content_dir = %r{(?:#{url}|\\?\/\\?\/?#{wp_content_dir})}i - - %r{#{content_dir}\\?/#{type}\\?/} - end - - # @param [ WpTarget ] wp_target - # - # @return [ Regex ] - def attribute_pattern(wp_target) - /\A#{item_pattern(wp_target)}([^\/]+)/i - end - - # @param [ WpTarget ] wp_target - # - # @return [ Regex ] - def code_pattern(wp_target) - /["'\(]#{item_pattern(wp_target)}([^\\\/\)"']+)/i - end - - # The default request parameters - # - # @return [ Hash ] - def request_params; { cache_ttl: 0, followlocation: true } end - - # @param [ WpTarget ] wp_target - # @param [ options ] options - # @option options [ Boolean ] :only_vulnerable - # @option options [ String ] :file The path to the file containing the targets - # - # @return [ Array ] - def targets_items(wp_target, options = {}) - item_class = self.item_class - vulns_file = self.vulns_file - - targets = target_items_from_type(wp_target, item_class, vulns_file, options[:type]) - - targets.uniq! { |t| t.name } - targets.sort_by { rand } - end - - # @param [ WpTarget ] wp_target - # @param [ Class ] item_class - # @param [ String ] vulns_file - # - # @return [ Array ] - def target_items_from_type(wp_target, item_class, vulns_file, type) - targets = [] - json = json(vulns_file) - - case type - when :vulnerable - items = json.select { |item| !json[item]['vulnerabilities'].empty? }.keys - when :popular - items = json.select { |item| json[item]['popular'] == true }.keys - when :all - items = json.keys - else - raise "Unknown type #{type}" - end - - items.each do |item| - targets << create_item( - item_class, - item, - wp_target, - vulns_file - ) - end - - targets - end - - # @param [ Class ] klass - # @param [ String ] name - # @param [ WpTarget ] wp_target - # @option [ String ] vulns_file - # - # @return [ WpItem ] - def create_item(klass, name, wp_target, vulns_file = nil) - klass.new( - wp_target.uri, - name: name, - vulns_file: vulns_file, - wp_content_dir: wp_target.wp_content_dir, - wp_plugins_dir: wp_target.wp_plugins_dir - ) - end - - # @param [ String ] file - # @param [ WpTarget ] wp_target - # @param [ Class ] item_class - # @param [ String ] vulns_file - # - # @return [ Array ] - def targets_items_from_file(file, wp_target, item_class, vulns_file) - targets = [] - - File.open(file, 'r') do |f| - f.readlines.collect do |item_name| - targets << create_item( - item_class, - item_name.strip, - wp_target, - vulns_file - ) - end - end - - targets - end - - # @return [ Class ] - def item_class - Object.const_get(self.to_s.gsub(/.$/, '')) - end - end -end diff --git a/lib/common/collections/wp_items/output.rb b/lib/common/collections/wp_items/output.rb deleted file mode 100644 index 6981c96a..00000000 --- a/lib/common/collections/wp_items/output.rb +++ /dev/null @@ -1,11 +0,0 @@ -# encoding: UTF-8 - -class WpItems < Array - module Output - - def output(verbose = false) - self.each { |item| item.output(verbose) } - end - - end -end diff --git a/lib/common/collections/wp_plugins.rb b/lib/common/collections/wp_plugins.rb deleted file mode 100644 index 955259c4..00000000 --- a/lib/common/collections/wp_plugins.rb +++ /dev/null @@ -1,8 +0,0 @@ -# encoding: UTF-8 - -require 'common/collections/wp_plugins/detectable' - -class WpPlugins < WpItems - extend WpPlugins::Detectable - -end diff --git a/lib/common/collections/wp_plugins/detectable.rb b/lib/common/collections/wp_plugins/detectable.rb deleted file mode 100644 index 3f271610..00000000 --- a/lib/common/collections/wp_plugins/detectable.rb +++ /dev/null @@ -1,77 +0,0 @@ -# encoding: UTF-8 - -class WpPlugins < WpItems - module Detectable - # @return [ String ] - def vulns_file - PLUGINS_FILE - end - - # @param [ WpTarget ] wp_target - # @param [ Hash ] options - # - # @return [ WpPlugins ] - def passive_detection(wp_target, options = {}) - detected = super(wp_target, options) - - detected += from_header(wp_target) - detected += from_content(wp_target) - - detected.uniq! { |i| i.name } - detected - end - - protected - - # X-Powered-By: W3 Total Cache/0.9.2.5 - # WP-Super-Cache: Served supercache file from PHP - # @param [ WpTarget ] wp_target - # - # @return [ WpPlugins ] - def from_header(wp_target) - headers = Browser.get(wp_target.url).headers - wp_plugins = WpPlugins.new(wp_target) - - if headers - powered_by = headers['X-Powered-By'].to_s - wp_super_cache = headers['wp-super-cache'].to_s - - if matches = /W3 Total Cache\/([0-9.]+)/i.match(powered_by) - wp_plugins.add('w3-total-cache', version: matches[1]) - end - - wp_plugins.add('wp-super-cache') if wp_super_cache =~ /supercache/i - end - - wp_plugins - end - - # - # /m, '') - # remove javascript stuff - page = page.gsub(/)<[^<]*)*<\/script>/m, '') - Digest::MD5.hexdigest(page) - end - - def homepage_hash - unless @homepage_hash - @homepage_hash = WebSite.page_hash(@uri.to_s) - end - @homepage_hash - end - - # Return the MD5 hash of a 404 page - def error_404_hash - unless @error_404_hash - non_existant_page = Digest::MD5.hexdigest(rand(999_999_999).to_s) + '.html' - @error_404_hash = WebSite.page_hash(@uri.merge(non_existant_page).to_s) - end - @error_404_hash - end - - # Only the first 700 bytes are checked to avoid the download - # of the whole file which can be very huge (like 2 Go) - # - # @param [ String ] log_url - # @param [ RegEx ] pattern - # - # @return [ Boolean ] - def self.has_log?(log_url, pattern) - log_body = Browser.get(log_url, headers: {'range' => 'bytes=0-700'}).body - log_body[pattern] ? true : false - end -end diff --git a/lib/wpscan/web_site/humans_txt.rb b/lib/wpscan/web_site/humans_txt.rb deleted file mode 100644 index e9eceaad..00000000 --- a/lib/wpscan/web_site/humans_txt.rb +++ /dev/null @@ -1,13 +0,0 @@ -# encoding: UTF-8 - -class WebSite - module HumansTxt - - # Gets the humans.txt URL - # @return [ String ] - def humans_url - @uri.clone.merge('humans.txt').to_s - end - - end -end diff --git a/lib/wpscan/web_site/interesting_headers.rb b/lib/wpscan/web_site/interesting_headers.rb deleted file mode 100644 index 31f826da..00000000 --- a/lib/wpscan/web_site/interesting_headers.rb +++ /dev/null @@ -1,44 +0,0 @@ -# encoding: UTF-8 - -class WebSite - module InterestingHeaders - - # Checks for interesting headers - # @return [ Array ] Interesting Headers - def interesting_headers - response = Browser.head(@uri.to_s) - headers = response.headers - # Header Names are case insensitve so convert them to upcase - headers_uppercase = headers.inject({}) do |hash, keys| - hash[keys[0].upcase] = keys[1] - hash - end - InterestingHeaders.known_headers.each do |h| - headers_uppercase.delete(h.upcase) - end - headers_uppercase.to_a.compact.sort - end - - protected - - # @return [ Array ] - def self.known_headers - %w{ - Location - Date - Content-Type - Content-Length - Connection - Etag - Expires - Last-Modified - Pragma - Vary - Cache-Control - X-Pingback - Accept-Ranges - } - end - - end -end diff --git a/lib/wpscan/web_site/robots_txt.rb b/lib/wpscan/web_site/robots_txt.rb deleted file mode 100644 index b9f6589f..00000000 --- a/lib/wpscan/web_site/robots_txt.rb +++ /dev/null @@ -1,70 +0,0 @@ -# encoding: UTF-8 - -class WebSite - module RobotsTxt - - # Checks if a robots.txt file exists - # @return [ Boolean ] - def has_robots? - Browser.get(robots_url).code == 200 - end - - # Gets a robots.txt URL - # @return [ String ] - def robots_url - @uri.clone.merge('robots.txt').to_s - end - - # Parse robots.txt - # @return [ Array ] URLs generated from robots.txt - def parse_robots_txt - return_object = [] - - # Make request - response = Browser.get(robots_url.to_s) - body = response.body - - # Get all allow and disallow urls - entries = body.scan(/^(?:dis)?allow:\s*(.*)$/i) - - # Did we get something? - if entries - # Remove any rubbish - entries = clean_uri(entries) - - # Sort - entries.sort! - - # Wordpress URL - wordpress_path = @uri.path - - # Each "boring" value as defined below, remove - RobotsTxt.known_dirs.each do |d| - entries.delete(d) - # Also delete when wordpress is installed in subdir - dir_with_subdir = "#{wordpress_path}/#{d}".gsub(/\/+/, '/') - entries.delete(dir_with_subdir) - end - - # Convert to full URIs - return_object = full_uri(entries) - end - return return_object - end - - protected - - # Useful ~ "function do_robots()" -> https://github.com/WordPress/WordPress/blob/master/wp-includes/functions.php - # - # @return [ Array ] - def self.known_dirs - %w{ - / - /wp-admin/ - /wp-admin/admin-ajax.php - /wp-includes/ - /wp-content/ - } - end - end -end diff --git a/lib/wpscan/web_site/security_txt.rb b/lib/wpscan/web_site/security_txt.rb deleted file mode 100644 index c8f8687e..00000000 --- a/lib/wpscan/web_site/security_txt.rb +++ /dev/null @@ -1,13 +0,0 @@ -# encoding: UTF-8 - -class WebSite - module SecurityTxt - - # Gets the security.txt URL - # @return [ String ] - def security_url - @uri.clone.merge('.well-known/security.txt').to_s - end - - end -end diff --git a/lib/wpscan/web_site/sitemap.rb b/lib/wpscan/web_site/sitemap.rb deleted file mode 100644 index 46140a03..00000000 --- a/lib/wpscan/web_site/sitemap.rb +++ /dev/null @@ -1,53 +0,0 @@ -# encoding: UTF-8 - -class WebSite - module Sitemap - - # Checks if a sitemap.txt file exists - # @return [ Boolean ] - def has_sitemap? - # Make the request - response = Browser.get(sitemap_url) - - # Make sure its HTTP 200 - return false unless response.code == 200 - - # Is there a sitemap value? - result = response.body.scan(/^sitemap\s*:\s*(.*)$/i) - return true if result[0] - return false - end - - # Get the robots.txt URL - # @return [ String ] - def sitemap_url - @uri.clone.merge('robots.txt').to_s - end - - # Parse robots.txt - # @return [ Array ] URLs generated from robots.txt - def parse_sitemap - return_object = [] - - # Make request - response = Browser.get(sitemap_url.to_s) - - # Get all allow and disallow urls - entries = response.body.scan(/^sitemap\s*:\s*(.*)$/i) - - # Did we get something? - if entries - # Remove any rubbish - entries = clean_uri(entries) - - # Sort - entries.sort! - - # Convert to full URIs - return_object = full_uri(entries) - end - return return_object - end - - end -end diff --git a/lib/wpscan/web_site/sql_file_export.rb b/lib/wpscan/web_site/sql_file_export.rb deleted file mode 100644 index 3a0f1e5e..00000000 --- a/lib/wpscan/web_site/sql_file_export.rb +++ /dev/null @@ -1,35 +0,0 @@ -# encoding: UTF-8 - -class WebSite - module SqlFileExport - - # Checks if a .sql file exists - # @return [ Array ] - def sql_file_export - export_files = [] - - self.sql_file_export_urls.each do |url| - response = Browser.get(url) - export_files << url if response.code == 200 && response.body =~ /INSERT INTO/ - end - - export_files - end - - # Gets a .sql export file URL - # @return [ Array ] - def sql_file_export_urls - urls = [] - host = @uri.host[/(^[\w|-]+)/,1] - - files = ["#{host}.sql", "#{host}.sql.gz", "#{host}.zip", 'db.sql', 'site.sql', 'database.sql', - 'data.sql', 'backup.sql', 'dump.sql', 'db_backup.sql', 'dbdump.sql', 'wordpress.sql', 'mysql.sql'] - - files.each do |file| - urls << @uri.clone.merge(file).to_s - end - - urls - end - end -end diff --git a/lib/wpscan/wp_target.rb b/lib/wpscan/wp_target.rb deleted file mode 100644 index f9f7c688..00000000 --- a/lib/wpscan/wp_target.rb +++ /dev/null @@ -1,184 +0,0 @@ -# encoding: UTF-8 - -require 'web_site' -require 'wp_target/wp_api' -require 'wp_target/wp_config_backup' -require 'wp_target/wp_custom_directories' -require 'wp_target/wp_full_path_disclosure' -require 'wp_target/wp_login_protection' -require 'wp_target/wp_must_use_plugins' -require 'wp_target/wp_readme' -require 'wp_target/wp_registrable' -require 'wp_target/wp_rss' - -class WpTarget < WebSite - include WpTarget::WpAPI - include WpTarget::WpConfigBackup - include WpTarget::WpCustomDirectories - include WpTarget::WpFullPathDisclosure - include WpTarget::WpLoginProtection - include WpTarget::WpMustUsePlugins - include WpTarget::WpReadme - include WpTarget::WpRegistrable - include WpTarget::WpRSS - - attr_reader :verbose - - def initialize(target_url, options = {}) - raise Exception.new('target_url can not be nil or empty') if target_url.nil? || target_url == '' - super(target_url) - - @verbose = options[:verbose] - @wp_content_dir = options[:wp_content_dir] - @wp_plugins_dir = options[:wp_plugins_dir] - @multisite = nil - @vhost = options[:vhost] - - Browser.instance.referer = url - if @vhost - Browser.instance.vhost = @vhost - end - - end - - # check if the target website is - # actually running wordpress. - def wordpress? - wordpress = false - - response = Browser.get_and_follow_location(@uri.to_s) - - # Note: in the future major WPScan version, change the user-agent to see - # if the response is a 200 ? - fail "The target is responding with a 403, this might be due to a WAF or a plugin.\n" \ - 'You should try to supply a valid user-agent via the --user-agent option or use the --random-agent option' if response.code == 403 - - dir = wp_content_dir ? wp_content_dir : 'wp-content' - - if response.body =~ /["'][^"']*\/#{Regexp.escape(dir)}\/[^"']*["']/i - wordpress = true - else - - if has_xml_rpc? - wordpress = true - else - response = Browser.get_and_follow_location(login_url) - - if response.code == 200 && response.body =~ %r{WordPress}i - wordpress = true - end - end - end - - wordpress - end - - def wordpress_hosted? - @uri.to_s =~ /\.wordpress\.com/i - end - - def login_url - url = @uri.merge('wp-login.php').to_s - - # Let's check if the login url is redirected (to https url for example) - redirection = redirection(url) - url = redirection if redirection - - url - end - - # Valid HTTP return codes - def self.valid_response_codes - [200, 301, 302, 401, 403, 500, 400] - end - - # @return [ WpTheme ] - # :nocov: - def theme - WpTheme.find(@uri) - end - # :nocov: - - # @param [ String ] versions_xml - # - # @return [ WpVersion ] - # :nocov: - def version(versions_xml) - WpVersion.find(@uri, wp_content_dir, wp_plugins_dir, versions_xml) - end - # :nocov: - - # The version is not yet considered - # - # @param [ String ] name - # @param [ String ] version - # - # @return [ Boolean ] - def has_plugin?(name, version = nil) - WpPlugin.new( - @uri, - name: name, - version: version, - wp_content_dir: wp_content_dir, - wp_plugins_dir: wp_plugins_dir - ).exists? - end - - # @return [ Boolean ] - def has_debug_log? - WebSite.has_log?(debug_log_url, %r{\[[^\]]+\] PHP (?:Warning|Error|Notice):}) - end - - # @return [ String ] - def debug_log_url - @uri.merge("#{wp_content_dir}/debug.log").to_s - end - - # @return [ String ] - def upload_dir_url - @uri.merge("#{wp_content_dir}/uploads/").to_s - end - - # @return [ String ] - def includes_dir_url - @uri.merge("wp-includes/").to_s - end - - # Script for replacing strings in wordpress databases - # reveals database credentials after hitting submit - # http://interconnectit.com/124/search-and-replace-for-wordpress-databases/ - # - # @return [ String ] - def search_replace_db_2_url - @uri.merge('searchreplacedb2.php').to_s - end - - # @return [ Boolean ] - def search_replace_db_2_exists? - resp = Browser.get(search_replace_db_2_url) - resp.code == 200 && resp.body[%r{by interconnect}i] - end - - # Script used to recover locked out admin users - # http://yoast.com/emergency-wordpress-access/ - # https://codex.wordpress.org/User:MichaelH/Orphaned_Plugins_needing_Adoption/Emergency - # - # @return [ String ] - def emergency_url - @uri.merge('emergency.php').to_s - end - - # @return [ Boolean ] - def emergency_exists? - resp = Browser.get(emergency_url) - resp.code == 200 && resp.body[%r{password}i] - end - - def upload_directory_listing_enabled? - directory_listing_enabled?(upload_dir_url) - end - - def include_directory_listing_enabled? - directory_listing_enabled?(includes_dir_url) - end -end diff --git a/lib/wpscan/wp_target/wp_api.rb b/lib/wpscan/wp_target/wp_api.rb deleted file mode 100644 index 5012e111..00000000 --- a/lib/wpscan/wp_target/wp_api.rb +++ /dev/null @@ -1,86 +0,0 @@ -# encoding: UTF-8 - -class WpTarget < WebSite - module WpAPI - - # Checks to see if the REST API is enabled - # - # This by default in a WordPress installation since 4.5+ - # @return [ Boolean ] - def has_api?(url) - # Make the request - response = Browser.get(url) - - # Able to view the output? - if valid_json?(response.body) && response.body != '' - # Read in JSON - data = JSON.parse(response.body) - - # If there is nothing there, return false - if data.empty? - return false - # WAF/API disabled response - elsif data.include?('message') and data['message'] =~ /Only authenticated users can access the REST API/ - return false - # Success! - elsif response.code == 200 - return true - end - end - - # Something went wrong - return false - end - - # @return [ String ] The API/JSON URL - def json_url - @uri.merge('/wp-json/').to_s - end - - # @return [ String ] The API/JSON URL to show users - def json_users_url - @uri.merge('/wp-json/wp/v2/users').to_s - end - - # @return [ String ] The API/JSON URL to show users - def json_get_users(url) - # Variables - users = [] - - # Make the request - response = Browser.get(url) - - # If not HTTP 200, return false - return false unless response.code == 200 - - # Able to view the output? - return false unless valid_json?(response.body) - - # Read in JSON - data = JSON.parse(response.body) - - # If there is nothing there, return false - return false if data.empty? - - # Add to array - data.each do |child| - row = [ child['id'], child['name'], child['link'] ] - users << row - end - - # Sort and uniq - users = users.sort.uniq - - if users and users.size >= 1 - # Feedback - grammar = grammar_s(users.size) - puts warning("#{users.size} user#{grammar} exposed via API: #{json_users_url}") - - # Print results - table = Terminal::Table.new(headings: ['ID', 'Name', 'URL'], - rows: users) - puts table - end - end - end -end diff --git a/lib/wpscan/wp_target/wp_config_backup.rb b/lib/wpscan/wp_target/wp_config_backup.rb deleted file mode 100644 index 076eff9a..00000000 --- a/lib/wpscan/wp_target/wp_config_backup.rb +++ /dev/null @@ -1,50 +0,0 @@ -# encoding: UTF-8 - -class WpTarget < WebSite - module WpConfigBackup - - # Checks to see if wp-config.php has a backup - # See http://www.feross.org/cmsploit/ - # @return [ Array ] Backup config files - def config_backup - found = [] - backups = WpConfigBackup.config_backup_files - browser = Browser.instance - hydra = browser.hydra - queue_count = 0 - - backups.each do |file| - file_url = @uri.merge(url_encode(file)).to_s - request = browser.forge_request(file_url) - - request.on_complete do |response| - if response.body[%r{define}i] and not response.body[%r{<\s?html}i] - found << file_url - end - end - - hydra.queue(request) - queue_count += 1 - - if queue_count == browser.max_threads - hydra.run - queue_count = 0 - end - end - - hydra.run - - found - end - - # @return [ Array ] - def self.config_backup_files - %w{ - wp-config.php~ #wp-config.php# wp-config.php.save .wp-config.php.swp wp-config.php.swp wp-config.php.swo - wp-config.php_bak wp-config.bak wp-config.php.bak wp-config.save wp-config.old wp-config.php.old - wp-config.php.orig wp-config.orig wp-config.php.original wp-config.original wp-config.txt - } # thanks to Feross.org for these - end - - end -end diff --git a/lib/wpscan/wp_target/wp_custom_directories.rb b/lib/wpscan/wp_target/wp_custom_directories.rb deleted file mode 100644 index 59956edb..00000000 --- a/lib/wpscan/wp_target/wp_custom_directories.rb +++ /dev/null @@ -1,49 +0,0 @@ -# encoding: UTF-8 - -class WpTarget < WebSite - module WpCustomDirectories - - # @return [ String ] The wp-content directory - def wp_content_dir - unless @wp_content_dir - index_body = Browser.get(@uri.to_s).body - uri_path = @uri.path # Only use the path because domain can be text or an IP - - if index_body[/\/wp-content\/(?:themes|plugins)\//i] || default_wp_content_dir_exists? - @wp_content_dir = 'wp-content' - else - domains_excluded = '(?:www\.)?(facebook|twitter)\.com' - @wp_content_dir = index_body[/(?:href|src)\s*=\s*(?:"|').+#{Regexp.escape(uri_path)}((?!#{domains_excluded})[^"']+)\/(?:themes|plugins)\/.*(?:"|')/i, 1] - end - end - - @wp_content_dir - end - - # @return [ Boolean ] - def default_wp_content_dir_exists? - response = Browser.get(@uri.merge('wp-content').to_s) - - if WpTarget.valid_response_codes.include?(response.code) - hash = WebSite.page_hash(response) - return true if hash != error_404_hash and hash != homepage_hash - end - - false - end - - # @return [ String ] The wp-plugins directory - def wp_plugins_dir - unless @wp_plugins_dir - @wp_plugins_dir = "#{wp_content_dir}/plugins" - end - @wp_plugins_dir - end - - # @return [ Boolean ] - def wp_plugins_dir_exists? - Browser.get(@uri.merge(wp_plugins_dir).to_s).code != 404 - end - - end -end diff --git a/lib/wpscan/wp_target/wp_full_path_disclosure.rb b/lib/wpscan/wp_target/wp_full_path_disclosure.rb deleted file mode 100644 index a530e7c9..00000000 --- a/lib/wpscan/wp_target/wp_full_path_disclosure.rb +++ /dev/null @@ -1,22 +0,0 @@ -# encoding: UTF-8 - -class WpTarget < WebSite - module WpFullPathDisclosure - # Check for Full Path Disclosure (FPD) - # - # @return [ Boolean ] - def has_full_path_disclosure? - Browser.get(full_path_disclosure_url).body[%r/Fatal error/i] ? true : false - end - - def full_path_disclosure_data - return nil unless has_full_path_disclosure? - Browser.get(full_path_disclosure_url).body[/Fatal error:.+? in (.+?) on/i, 1] - end - - # @return [ String ] - def full_path_disclosure_url - @uri.merge('wp-includes/rss-functions.php').to_s - end - end -end diff --git a/lib/wpscan/wp_target/wp_login_protection.rb b/lib/wpscan/wp_target/wp_login_protection.rb deleted file mode 100644 index f94918d1..00000000 --- a/lib/wpscan/wp_target/wp_login_protection.rb +++ /dev/null @@ -1,110 +0,0 @@ -# encoding: UTF-8 - -class WpTarget < WebSite - module WpLoginProtection - - LOGIN_PROTECTION_METHOD_PATTERN = /^has_(.*)_protection\?/i - # Used as cache - @login_protection_plugin = nil - - def has_login_protection? - !login_protection_plugin.nil? - end - - # Checks if a login protection plugin is enabled - # return a WpPlugin object or nil if no one is found - def login_protection_plugin - unless @login_protection_plugin - protected_methods.grep(LOGIN_PROTECTION_METHOD_PATTERN).each do |symbol_to_call| - - if send(symbol_to_call) - plugin_name = symbol_to_call[LOGIN_PROTECTION_METHOD_PATTERN, 1].gsub('_', '-') - - return @login_protection_plugin = WpPlugin.new( - @uri, - name: plugin_name, - wp_content_dir: wp_content_dir, - wp_plugins_dir: wp_plugins_dir - ) - end - end - @login_protection_plugin = nil - end - @login_protection_plugin - end - - protected - # Thanks to Alip Aswalid for providing this method. - # http://wordpress.org/extend/plugins/login-lockdown/ - def has_login_lockdown_protection? - Browser.get(login_url).body =~ %r{Login LockDown}i ? true : false - end - - # http://wordpress.org/extend/plugins/login-lock/ - def has_login_lock_protection? - Browser.get(login_url).body =~ %r{LOGIN LOCK} ? true : false - end - - # http://wordpress.org/extend/plugins/better-wp-security/ - def has_better_wp_security_protection? - Browser.get(better_wp_security_url).code != 404 - end - - def plugin_url(plugin_name) - WpPlugin.new( - @uri, - name: plugin_name, - wp_content_dir: wp_content_dir, - wp_plugins_dir: wp_plugins_dir - ).url - end - - def better_wp_security_url - plugin_url('better-wp-security/') - end - - # http://wordpress.org/extend/plugins/simple-login-lockdown/ - def has_simple_login_lockdown_protection? - Browser.get(simple_login_lockdown_url).code != 404 - end - - def simple_login_lockdown_url - plugin_url('simple-login-lockdown/') - end - - # http://wordpress.org/extend/plugins/login-security-solution/ - def has_login_security_solution_protection? - Browser.get(login_security_solution_url).code != 404 - end - - def login_security_solution_url - plugin_url('login-security-solution') - end - - # http://wordpress.org/extend/plugins/limit-login-attempts/ - def has_limit_login_attempts_protection? - Browser.get(limit_login_attempts_url).code != 404 - end - - def limit_login_attempts_url - plugin_url('limit-login-attempts') - end - - # http://wordpress.org/extend/plugins/bluetrait-event-viewer/ - def has_bluetrait_event_viewer_protection? - Browser.get(bluetrait_event_viewer_url).code != 404 - end - - def bluetrait_event_viewer_url - plugin_url('bluetrait-event-viewer') - end - - # https://wordpress.org/plugins/security-protection/ - def has_security_protection_protection? - Nokogiri::HTML(Browser.get(login_url).body).css('script').each do |node| - return true if node['src'] =~ /security-protection.js/i - end - false - end - end -end diff --git a/lib/wpscan/wp_target/wp_must_use_plugins.rb b/lib/wpscan/wp_target/wp_must_use_plugins.rb deleted file mode 100644 index edf52fe6..00000000 --- a/lib/wpscan/wp_target/wp_must_use_plugins.rb +++ /dev/null @@ -1,24 +0,0 @@ -# encoding: UTF-8 - -class WpTarget < WebSite - module WpMustUsePlugins - # Checks to see if the must use plugin folder exists - # - # @return [ Boolean ] - def has_must_use_plugins? - response = Browser.get(must_use_url) - - if response && [200, 401, 403].include?(response.code) - hash = WebSite.page_hash(response) - return true if hash != error_404_hash && hash != homepage_hash - end - - false - end - - # @return [ String ] The must use plugins directory URL - def must_use_url - @uri.merge("#{wp_content_dir}/mu-plugins/").to_s - end - end -end diff --git a/lib/wpscan/wp_target/wp_readme.rb b/lib/wpscan/wp_target/wp_readme.rb deleted file mode 100644 index db57d563..00000000 --- a/lib/wpscan/wp_target/wp_readme.rb +++ /dev/null @@ -1,27 +0,0 @@ -# encoding: UTF-8 - -class WpTarget < WebSite - module WpReadme - - # Checks to see if the readme.html file exists - # - # This file comes by default in a wordpress installation, - # and if deleted is reinstated with an upgrade. - # - # @return [ Boolean ] - def has_readme? - response = Browser.get(readme_url) - - unless response.code == 404 - return response.body =~ %r{wordpress}i ? true : false - end - false - end - - # @return [ String ] The readme URL - def readme_url - @uri.merge('readme.html').to_s - end - - end -end diff --git a/lib/wpscan/wp_target/wp_registrable.rb b/lib/wpscan/wp_target/wp_registrable.rb deleted file mode 100644 index 72c4c307..00000000 --- a/lib/wpscan/wp_target/wp_registrable.rb +++ /dev/null @@ -1,53 +0,0 @@ -# encoding: UTF-8 - -class WpTarget < WebSite - module WpRegistrable - - # Should check wp-login.php if registration is enabled or not - # - # @return [ Boolean ] - def registration_enabled? - resp = Browser.get(registration_url) - # redirect only on non multi sites - if resp.code == 302 and resp.headers_hash['location'] =~ /wp-login\.php\?registration=disabled/i - enabled = false - # multi site registration form - elsif resp.code == 200 and resp.body =~ /
/i - enabled = true - # normal registration form - elsif resp.code == 200 and resp.body =~ / - homepage_body[%r{}i, 1] - end - - - # Gets all the authors from the RSS feed - # - # @return [ string ] - def rss_authors(url) - # Variables - users = [] - - # Make the request - response = Browser.get(url, followlocation: true) - - # Valid repose to view? HTTP 200? - return false unless response.code == 200 - - # Get output - data = response.body - - # If there is nothing there, return false - return false if data.empty? - - begin - # Read in RSS/XML - xml = Nokogiri::XML(data) - rescue - puts critical("Missformed XML") - return false - end - - begin - # Look for item - xml.xpath('//item/dc:creator').each do |node| - #Format: - users << [%r{.*}i.match(node).to_s] - end - rescue - puts critical("Missing Author field. Maybe non-standard WordPress RSS feed?") - return false - end - - # Sort and uniq - users = users.sort_by { |user| user.to_s.downcase }.uniq - - if users and users.size >= 1 - # Feedback - grammar = grammar_s(users.size) - puts warning("Detected #{users.size} user#{grammar} from RSS feed:") - - # Print results - table = Terminal::Table.new(headings: ['Name'], - rows: users) - puts table - end - end - end -end diff --git a/lib/wpscan/wpscan_helper.rb b/lib/wpscan/wpscan_helper.rb deleted file mode 100644 index f2fc5470..00000000 --- a/lib/wpscan/wpscan_helper.rb +++ /dev/null @@ -1,193 +0,0 @@ -# encoding: UTF-8 - -require File.expand_path(File.join(__dir__, '..', 'common', 'common_helper')) - -require_files_from_directory(WPSCAN_LIB_DIR, '**/*.rb') - -# wpscan usage -def usage - script_name = $0 - puts - puts 'Examples :' - puts - puts '-Further help ...' - puts "ruby #{script_name} --help" - puts - puts "-Do 'non-intrusive' checks ..." - puts "ruby #{script_name} --url www.example.com" - puts - puts '-Do wordlist password brute force on enumerated users using 50 threads ...' - puts "ruby #{script_name} --url www.example.com --wordlist darkc0de.lst --threads 50" - puts - puts "-Do wordlist password brute force on the 'admin' username only ..." - puts "ruby #{script_name} --url www.example.com --wordlist darkc0de.lst --username admin" - puts - puts '-Enumerate installed plugins ...' - puts "ruby #{script_name} --url www.example.com --enumerate p" - puts - puts '-Enumerate installed themes ...' - puts "ruby #{script_name} --url www.example.com --enumerate t" - puts - puts '-Enumerate users (from 1 - 10)...' - puts "ruby #{script_name} --url www.example.com --enumerate u" - puts - puts '-Enumerate users (from 1 - 20)...' - puts "ruby #{script_name} --url www.example.com --enumerate u[1-20]" - puts - puts '-Enumerate installed timthumbs ...' - puts "ruby #{script_name} --url www.example.com --enumerate tt" - puts - puts '-Use a HTTP proxy ...' - puts "ruby #{script_name} --url www.example.com --proxy 127.0.0.1:8118" - puts - puts '-Use a SOCKS5 proxy ... (cURL >= v7.21.7 needed)' - puts "ruby #{script_name} --url www.example.com --proxy socks5://127.0.0.1:9000" - puts - puts '-Use custom content directory ...' - puts "ruby #{script_name} -u www.example.com --wp-content-dir custom-content" - puts - puts '-Use custom plugins directory ...' - puts "ruby #{script_name} -u www.example.com --wp-plugins-dir wp-content/custom-plugins" - puts - puts '-Update the Database ...' - puts "ruby #{script_name} --update" - puts - puts '-Debug output ...' - puts "ruby #{script_name} --url www.example.com --debug-output 2>debug.log" - puts - puts 'See README for further information.' - puts -end - -# command help -def help - puts 'Help :' - puts - puts 'Some values are settable in a config file, see the example.conf.json' - puts - puts '--update Update the database to the latest version.' - puts '--url | -u The WordPress URL/domain to scan.' - puts '--force | -f Forces WPScan to not check if the remote site is running WordPress.' - puts '--enumerate | -e [option(s)] Enumeration.' - puts ' option :' - puts ' u usernames from id 1 to 10' - puts ' u[10-20] usernames from id 10 to 20 (you must write [] chars)' - puts ' p plugins' - puts ' vp only vulnerable plugins' - puts ' ap all plugins (can take a long time)' - puts ' tt timthumbs' - puts ' t themes' - puts ' vt only vulnerable themes' - puts ' at all themes (can take a long time)' - puts ' Multiple values are allowed : "-e tt,p" will enumerate timthumbs and plugins' - puts ' If no option is supplied, the default is "vt,tt,u,vp"' - puts - puts '--exclude-content-based ""' - puts ' Used with the enumeration option, will exclude all occurrences based on the regexp or string supplied.' - puts ' You do not need to provide the regexp delimiters, but you must write the quotes (simple or double).' - puts '--config-file | -c Use the specified config file, see the example.conf.json.' - puts '--user-agent | -a Use the specified User-Agent.' - puts '--cookie String to read cookies from.' - puts '--random-agent | -r Use a random User-Agent.' - puts '--follow-redirection If the target url has a redirection, it will be followed without asking if you wanted to do so or not' - puts '--batch Never ask for user input, use the default behaviour.' - puts '--no-color Do not use colors in the output.' - puts '--log [filename] Creates a log.txt file with WPScan\'s output if no filename is supplied. Otherwise the filename is used for logging.' - puts '--no-banner Prevents the WPScan banner from being displayed.' - puts '--disable-accept-header Prevents WPScan sending the Accept HTTP header.' - puts '--disable-referer Prevents setting the Referer header.' - puts '--disable-tls-checks Disables SSL/TLS certificate verification.' - puts '--wp-content-dir WPScan try to find the content directory (ie wp-content) by scanning the index page, however you can specify it.' - puts ' Subdirectories are allowed.' - puts '--wp-plugins-dir Same thing than --wp-content-dir but for the plugins directory.' - puts ' If not supplied, WPScan will use wp-content-dir/plugins. Subdirectories are allowed' - puts '--proxy <[protocol://]host:port> Supply a proxy. HTTP, SOCKS4 SOCKS4A and SOCKS5 are supported.' - puts ' If no protocol is given (format host:port), HTTP will be used.' - puts '--proxy-auth Supply the proxy login credentials.' - puts '--basic-auth Set the HTTP Basic authentication.' - puts '--wordlist | -w Supply a wordlist for the password brute forcer.' - puts '--username | -U Only brute force the supplied username.' - puts '--usernames Only brute force the usernames from the file.' - puts '--cache-dir Set the cache directory.' - puts '--cache-ttl Typhoeus cache TTL.' - puts '--request-timeout Request Timeout.' - puts '--connect-timeout Connect Timeout.' - puts '--threads | -t The number of threads to use when multi-threading requests.' - puts '--throttle Milliseconds to wait before doing another web request. If used, the --threads should be set to 1.' - puts '--help | -h This help screen.' - puts '--verbose | -v Verbose output.' - puts '--version Output the current version and exit.' - puts -end - - -def clean_uri(entries) - # Extract elements - entries.flatten! - # Remove any leading/trailing spaces - entries.collect{|x| x.strip || x } - # End Of Line issues - entries.collect{|x| x.chomp! || x } - # Remove nil's - entries.compact - # Unique values only - entries.uniq! - - return entries -end - -# Return the full URL -def full_uri(entries) - return_object = [] - # Each value now, try and make it a full URL - entries.each do |d| - begin - temp = @uri.clone - temp.path = d.strip - rescue URI::Error - temp = d.strip - end - return_object << temp.to_s - end - - return return_object -end - -# Parse humans.txt -# @return [ Array ] URLs generated from humans.txt -def parse_txt(url) - return_object = [] - response = Browser.get(url.to_s) - body = response.body - - # Get all non-comments - entries = body.split(/\n/) - - # Did we get something? - if entries - # Remove any rubbish - entries = clean_uri(entries) - end - return return_object -end - - -# Hook to check if the target if down during the scan -# And have the number of requests performed to display at the end of the scan -# The target is considered down after 30 requests with status = 0 -down = 0 -@total_requests_done = 0 - -Typhoeus.on_complete do |response| - next if response.cached? - - down += 1 if response.code == 0 - @total_requests_done += 1 - - fail 'The target seems to be down' if down >= 30 - - next unless Browser.instance.throttle > 0 - - sleep(Browser.instance.throttle) -end - diff --git a/lib/wpscan/wpscan_options.rb b/lib/wpscan/wpscan_options.rb deleted file mode 100644 index 7efbf790..00000000 --- a/lib/wpscan/wpscan_options.rb +++ /dev/null @@ -1,314 +0,0 @@ -# encoding: UTF-8 - -class WpscanOptions - ACCESSOR_OPTIONS = [ - :batch, - :enumerate_plugins, - :enumerate_only_vulnerable_plugins, - :enumerate_all_plugins, - :enumerate_themes, - :enumerate_only_vulnerable_themes, - :enumerate_all_themes, - :enumerate_timthumbs, - :enumerate_usernames, - :enumerate_usernames_range, - :no_color, - :log, - :proxy, - :proxy_auth, - :threads, - :url, - :vhost, - :wordlist, - :force, - :update, - :verbose, - :username, - :usernames, - :password, - :follow_redirection, - :wp_content_dir, - :wp_plugins_dir, - :help, - :config_file, - :cookie, - :exclude_content_based, - :basic_auth, - :debug_output, - :version, - :user_agent, - :random_agent, - :cache_ttl, - :request_timeout, - :connect_timeout, - :max_threads, - :no_banner, - :throttle, - :disable_accept_header, - :disable_referer, - :cache_dir, - :disable_tls_checks - ] - - attr_accessor *ACCESSOR_OPTIONS - - def initialize - ACCESSOR_OPTIONS.each do |option| - instance_variable_set("@#{option}", nil) - end - end - - def url=(url) - raise Exception.new('Empty URL given') if url.nil? || url == '' - - url = Addressable::URI.parse(url).normalize.to_s unless url.ascii_only? - - @url = URI.parse(add_http_protocol(url)).to_s - end - - def vhost=(vhost) - @vhost = vhost - end - - def threads=(threads) - @threads = threads.is_a?(Integer) ? threads : threads.to_i - end - - def wordlist=(wordlist) - if File.exists?(wordlist) || wordlist == '-' - @wordlist = wordlist - else - raise "The file #{wordlist} does not exist" - end - end - - def usernames=(file) - fail "The file #{file} does not exist" unless File.exists?(file) - - @usernames = file - end - - def proxy=(proxy) - if proxy.index(':') == nil - raise 'Invalid proxy format. Should be host:port.' - else - @proxy = proxy - end - end - - def proxy_auth=(auth) - if auth.index(':') == nil - raise 'Invalid proxy auth format, username:password expected' - else - @proxy_auth = auth - end - end - - def enumerate_plugins=(enumerate_plugins) - if enumerate_plugins === true and (@enumerate_all_plugins === true or @enumerate_only_vulnerable_plugins === true) - raise 'Please choose only one plugin enumeration option' - else - @enumerate_plugins = enumerate_plugins - end - end - - def enumerate_only_vulnerable_plugins=(enumerate_only_vulnerable_plugins) - if enumerate_only_vulnerable_plugins === true and (@enumerate_all_plugins === true or @enumerate_plugins === true) - raise 'Please choose only one plugin enumeration option' - else - @enumerate_only_vulnerable_plugins = enumerate_only_vulnerable_plugins - end - end - - def enumerate_all_plugins=(enumerate_all_plugins) - if enumerate_all_plugins === true and (@enumerate_plugins === true or @enumerate_only_vulnerable_plugins === true) - raise 'Please choose only one plugin enumeration option' - else - @enumerate_all_plugins = enumerate_all_plugins - end - end - - def enumerate_themes=(enumerate_themes) - if enumerate_themes === true and (@enumerate_all_themes === true or @enumerate_only_vulnerable_themes === true) - raise 'Please choose only one theme enumeration option' - else - @enumerate_themes = enumerate_themes - end - end - - def enumerate_only_vulnerable_themes=(enumerate_only_vulnerable_themes) - if enumerate_only_vulnerable_themes === true and (@enumerate_all_themes === true or @enumerate_themes === true) - raise 'Please choose only one theme enumeration option' - else - @enumerate_only_vulnerable_themes = enumerate_only_vulnerable_themes - end - end - - def enumerate_all_themes=(enumerate_all_themes) - if enumerate_all_themes === true and (@enumerate_themes === true or @enumerate_only_vulnerable_themes === true) - raise 'Please choose only one theme enumeration option' - else - @enumerate_all_themes = enumerate_all_themes - end - end - - def debug_output=(debug_output) - Typhoeus::Config.verbose = debug_output - end - - def has_options? - !to_h.empty? - end - - def random_agent=(useless) - @user_agent = get_random_user_agent - end - - # return Hash - def to_h - options = {} - - ACCESSOR_OPTIONS.each do |option| - instance_variable = instance_variable_get("@#{option}") - - unless instance_variable.nil? - options[:"#{option}"] = instance_variable - end - end - options - end - - # Will load the options from ARGV - # return WpscanOptions - def self.load_from_arguments - wpscan_options = WpscanOptions.new - - if ARGV.length > 0 - WpscanOptions.get_opt_long.each do |opt, arg| - wpscan_options.set_option_from_cli(opt, arg) - end - end - - wpscan_options - end - - # string cli_option : --url, -u, --proxy etc - # string cli_value : the option value - def set_option_from_cli(cli_option, cli_value) - - if WpscanOptions.is_long_option?(cli_option) - self.send( - WpscanOptions.option_to_instance_variable_setter(cli_option), - cli_value - ) - elsif cli_option === '--enumerate' # Special cases - # Default value if no argument is given - cli_value = 'vt,tt,u,vp' if cli_value.length == 0 - - enumerate_options_from_string(cli_value) - else - text = "Unknown option : #{cli_option}" - text << " with value #{cli_value}" if (cli_value && !cli_value.empty?) - raise text - end - end - - # Will set enumerate_* from the string value - # IE : if value = vp => :enumerate_only_vulnerable_plugins will be set to true - # multiple enumeration are possible : 'u,p' => :enumerate_usernames and :enumerate_plugins - # Special case for usernames, a range is possible : u[1-10] will enumerate usernames from 1 to 10 - def enumerate_options_from_string(value) - # Usage of self is mandatory because there are overridden setters - - value = value.split(',').map { |c| c.downcase } - - self.enumerate_only_vulnerable_plugins = true if value.include?('vp') - - self.enumerate_plugins = true if value.include?('p') - - self.enumerate_all_plugins = true if value.include?('ap') - - @enumerate_timthumbs = true if value.include?('tt') - - self.enumerate_only_vulnerable_themes = true if value.include?('vt') - - self.enumerate_themes = true if value.include?('t') - - self.enumerate_all_themes = true if value.include?('at') - - value.grep(/^u/) do |username_enum_value| - @enumerate_usernames = true - # Check for usernames range - matches = %r{\[([\d]+)-([\d]+)\]}.match(username_enum_value) - if matches - @enumerate_usernames_range = (matches[1].to_i..matches[2].to_i) - end - end - - end - - protected - # Even if a short option is given (IE : -u), the long one will be returned (IE : --url) - def self.get_opt_long - GetoptLong.new( - ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT], - ['--vhost',GetoptLong::OPTIONAL_ARGUMENT], - ['--enumerate', '-e', GetoptLong::OPTIONAL_ARGUMENT], - ['--username', '-U', GetoptLong::REQUIRED_ARGUMENT], - ['--usernames', GetoptLong::REQUIRED_ARGUMENT], - ['--wordlist', '-w', GetoptLong::REQUIRED_ARGUMENT], - ['--threads', '-t', GetoptLong::REQUIRED_ARGUMENT], - ['--force', '-f', GetoptLong::NO_ARGUMENT], - ['--user-agent', '-a', GetoptLong::REQUIRED_ARGUMENT], - ['--random-agent', '-r', GetoptLong::NO_ARGUMENT], - ['--help', '-h', GetoptLong::NO_ARGUMENT], - ['--verbose', '-v', GetoptLong::NO_ARGUMENT], - ['--proxy', GetoptLong::REQUIRED_ARGUMENT], - ['--proxy-auth', GetoptLong::REQUIRED_ARGUMENT], - ['--update', GetoptLong::NO_ARGUMENT], - ['--follow-redirection', GetoptLong::NO_ARGUMENT], - ['--wp-content-dir', GetoptLong::REQUIRED_ARGUMENT], - ['--wp-plugins-dir', GetoptLong::REQUIRED_ARGUMENT], - ['--config-file', '-c', GetoptLong::REQUIRED_ARGUMENT], - ['--exclude-content-based', GetoptLong::REQUIRED_ARGUMENT], - ['--basic-auth', GetoptLong::REQUIRED_ARGUMENT], - ['--debug-output', GetoptLong::NO_ARGUMENT], - ['--version', GetoptLong::NO_ARGUMENT], - ['--cache-ttl', GetoptLong::REQUIRED_ARGUMENT], - ['--request-timeout', GetoptLong::REQUIRED_ARGUMENT], - ['--connect-timeout', GetoptLong::REQUIRED_ARGUMENT], - ['--batch', GetoptLong::NO_ARGUMENT], - ['--no-color', GetoptLong::NO_ARGUMENT], - ['--cookie', GetoptLong::REQUIRED_ARGUMENT], - ['--log', GetoptLong::OPTIONAL_ARGUMENT], - ['--no-banner', GetoptLong::NO_ARGUMENT], - ['--throttle', GetoptLong::REQUIRED_ARGUMENT], - ['--disable-accept-header', GetoptLong::NO_ARGUMENT], - ['--disable-referer', GetoptLong::NO_ARGUMENT], - ['--cache-dir', GetoptLong::REQUIRED_ARGUMENT], - ['--disable-tls-checks', GetoptLong::NO_ARGUMENT], - ) - end - - def self.is_long_option?(option) - ACCESSOR_OPTIONS.include?(:"#{WpscanOptions.clean_option(option)}") - end - - # Will removed the '-' or '--' chars at the beginning of option - # and replace any remaining '-' by '_' - # - # param string option - # return string - def self.clean_option(option) - cleaned_option = option.gsub(/^--?/, '') - cleaned_option.gsub(/-/, '_') - end - - def self.option_to_instance_variable_setter(option) - cleaned_option = WpscanOptions.clean_option(option) - option_syms = ACCESSOR_OPTIONS.grep(%r{^#{cleaned_option}$}) - - option_syms.length == 1 ? :"#{option_syms.at(0)}=" : nil - end - -end diff --git a/spec/cache/.gitignore b/spec/cache/.gitignore deleted file mode 100644 index 5e7d2734..00000000 --- a/spec/cache/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/spec/lib/common/browser_spec.rb b/spec/lib/common/browser_spec.rb deleted file mode 100644 index 6b2679ad..00000000 --- a/spec/lib/common/browser_spec.rb +++ /dev/null @@ -1,264 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe Browser do - it_behaves_like 'Browser::Actions' - it_behaves_like 'Browser::Options' - - CONFIG_FILE_WITHOUT_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser.conf.json' - CONFIG_FILE_WITH_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser.conf_proxy.json' - #CONFIG_FILE_WITH_PROXY_AND_AUTH = SPEC_FIXTURES_CONF_DIR + '/browser.conf_proxy_auth.json' - - subject(:browser) { - Browser.reset - Browser.instance(options) - } - let(:options) { {} } - let(:instance_vars_to_check) { - ['proxy', 'max_threads', 'cache_ttl', 'request_timeout', 'connect_timeout'] - } - let(:json_config_without_proxy) { JSON.parse(File.read(CONFIG_FILE_WITHOUT_PROXY)) } - let(:json_config_with_proxy) { JSON.parse(File.read(CONFIG_FILE_WITH_PROXY)) } - - def check_instance_variables(browser, json_expected_vars) - json_expected_vars['max_threads'] ||= 20 # max_thread can not be nil - - instance_vars_to_check.each do |variable_name| - expect(browser.send(:"#{variable_name}")).to be === json_expected_vars[variable_name] - end - end - - describe 'Singleton' do - it 'should not allow #new' do - expect { Browser.new }.to raise_error - end - end - - describe '::instance' do - after { check_instance_variables(browser, @json_expected_vars) } - - context "when :config_file = #{CONFIG_FILE_WITH_PROXY}" do - let(:options) { { config_file: CONFIG_FILE_WITH_PROXY } } - - it 'will check the instance vars' do - @json_expected_vars = json_config_with_proxy - end - end - - context 'when options[:cache_dir]' do - let(:cache_dir) { CACHE_DIR + '/somewhere' } - let(:options) { { cache_dir: cache_dir } } - - after { expect(subject.cache_dir).to eq cache_dir } - - it 'sets @cache_dir' do - @json_expected_vars = json_config_without_proxy - end - end - end - - describe '#load_config' do - context 'when config_file is a symlink' do - let(:config_file) { './rspec_symlink' } - - it 'raises an error' do - File.symlink('./testfile', config_file) - expect { browser.load_config(config_file) }.to raise_error('[ERROR] Config file is a symlink.') - File.unlink(config_file) - end - end - - context 'otherwise' do - after do - browser.load_config(@config_file) - check_instance_variables(browser, @expected) - end - - it 'sets the correct variables' do - @config_file = CONFIG_FILE_WITH_PROXY - @expected = json_config_without_proxy.merge(json_config_with_proxy) - end - end - end - - describe '::append_params_header_field' do - after :each do - expect(Browser.append_params_header_field( - @params, - @field, - @field_value - )).to be === @expected - end - - context 'when there is no headers' do - it 'create the header and set the field' do - @params = { somekey: 'somevalue' } - @field = 'User-Agent' - @field_value = 'FakeOne' - @expected = { somekey: 'somevalue', headers: { 'User-Agent' => 'FakeOne' } } - end - end - - context 'when there are headers' do - context 'when the field already exists' do - it 'does not replace it' do - @params = { somekey: 'somevalue', headers: { 'Location' => 'SomeLocation' } } - @field = 'Location' - @field_value = 'AnotherLocation' - @expected = @params - end - end - - context 'when the field is not present' do - it 'sets the field' do - @params = { somekey: 'somevalue', headers: { 'Auth' => 'user:pass' } } - @field = 'UA' - @field_value = 'FF' - @expected = { somekey: 'somevalue', headers: { 'Auth' => 'user:pass', 'UA' => 'FF' } } - end - end - end - end - - describe '#merge_request_params' do - let(:params) { {} } - let(:cookie_jar) { CACHE_DIR + '/browser/cookie-jar' } - let(:user_agent) { 'SomeUA' } - let(:default_expectation) { - { - cache_ttl: 250, - cookiejar: cookie_jar, cookiefile: cookie_jar, - timeout: 60, connecttimeout: 10, - maxredirs: 3, - referer: nil - } - } - - after :each do - browser.user_agent = user_agent - browser.cache_ttl = 250 - - expect(browser.merge_request_params(params)).to eq @expected - expect(Typhoeus::Config.user_agent).to eq user_agent - end - - it 'sets the User-Agent header field and cache_ttl' do - @expected = default_expectation - end - - context 'when @user_agent' do - let(:user_agent) { 'test' } - - it 'sets the User-Agent' do - @expected = default_expectation - end - end - - context 'when @proxy' do - let(:proxy) { '127.0.0.1:9050' } - let(:proxy_expectation) { default_expectation.merge(proxy: proxy) } - - it 'merges the proxy' do - browser.proxy = proxy - @expected = proxy_expectation - end - - context 'when @proxy_auth' do - it 'sets the proxy_auth' do - browser.proxy = proxy - browser.proxy_auth = 'user:pass' - @expected = proxy_expectation.merge(proxyuserpwd: 'user:pass') - end - end - end - - context 'when @request_timeout' do - it 'gives an Integer' do - browser.request_timeout = '10' - - @expected = default_expectation.merge(timeout: 10) - end - end - - context 'when @basic_auth' do - it 'appends the basic_auth' do - browser.basic_auth = 'user:pass' - @expected = default_expectation.merge( - headers: { 'Authorization' => 'Basic ' + Base64.encode64('user:pass').chomp } - ) - end - end - - context 'when the cache_ttl is alreday set' do - let(:params) { { cache_ttl: 500 } } - - it 'does not override it' do - @expected = default_expectation.merge(params) - end - end - - context 'when the maxredirs is alreday set' do - let(:params) { { maxredirs: 100 } } - - it 'does not override it' do - @expected = default_expectation.merge(params) - end - end - - context 'when @cookie' do - let(:cookie) { 'foor=bar;bar=foo' } - before { browser.cookie = cookie } - - it 'sets the cookie' do - @expected = default_expectation.merge(cookie: cookie) - end - end - - context 'when @disable_tls_checks' do - it 'disables tls checks' do - browser.disable_tls_checks = true - @expected = default_expectation.merge(ssl_verifypeer: 0, ssl_verifyhost: 0) - end - end - end - - describe '#forge_request' do - let(:url) { 'http://example.localhost' } - - it 'returns the correct Typhoeus::Request' do - allow(subject).to receive_messages(merge_request_params: { cache_ttl: 10 }) - - request = subject.forge_request(url) - expect(request).to be_a Typhoeus::Request - expect(request.url).to eq url - expect(request.cache_ttl).to eq 10 - end - - end - - describe 'testing caching' do - it 'should only do 1 request, and retrieve the other one from the cache' do - - url = 'http://example.localhost' - - stub_request(:get, url).to_return(status: 200, body: 'Hello World !') - - response1 = Browser.get(url) - response2 = Browser.get(url) - - expect(response1.body).to eq response2.body - #WebMock.should have_requested(:get, url).times(1) # This one fail, dunno why :s (but it works without mock) - end - end - - describe 'testing UTF8' do - it 'should not throw an encoding exception' do - url = SPEC_FIXTURES_DIR + '/utf8.html' - stub_request(:get, url).to_return(status: 200, body: File.read(url)) - - response = Browser.get(url) - expect { response.body }.to_not raise_error - end - end -end diff --git a/spec/lib/common/cache_file_store_spec.rb b/spec/lib/common/cache_file_store_spec.rb deleted file mode 100644 index c9db6b7d..00000000 --- a/spec/lib/common/cache_file_store_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe CacheFileStore do - let(:cache_dir) { SPEC_CACHE_DIR + '/cache_file_store' } - - before :each do - Dir.delete(cache_dir) rescue nil - - @cache = CacheFileStore.new(cache_dir) - end - - after :each do - @cache.clean - end - - describe '#storage_path' do - it 'returns the storage path given in the #new' do - expect(@cache.storage_path).to match(/#{cache_dir}/) - end - end - - describe '#serializer' do - it 'should return the default serializer : Marshal' do - expect(@cache.serializer).to eq Marshal - expect(@cache.serializer).not_to eq YAML - end - end - - describe '#clean' do - it "should remove all files from the cache dir (#{@cache_dir}" do - # clean is executed by other tests before - before = count_files_in_dir(@cache.cache_dir) - test_dir = File.expand_path("#{@cache.cache_dir}/test") - Dir.mkdir test_dir - #change the modification date - %x[ touch -t 200701310846.26 #{test_dir} ] - expect(count_files_in_dir(@cache.cache_dir)).to eq (before + 1) - @cache.clean - expect(count_files_in_dir(@cache.cache_dir)).to eq before - end - end - - describe '#read_entry' do - after { expect(@cache.read_entry(key)).to eq @expected } - - context 'when the entry does not exist' do - let(:key) { Digest::SHA1.hexdigest('hello world') } - - it 'should return nil' do - @expected = nil - end - end - - context 'when the file exist but is empty (marshal data too short error)' do - let(:key) { 'empty-file' } - - it 'returns nil' do - File.new(File.join(@cache.storage_path, key), File::CREAT) - - @expected = nil - end - end - end - - describe '#write_entry, #read_entry' do - - after :each do - @cache.write_entry(@key, @data, @timeout) - expect(@cache.read_entry(@key)).to be === @expected - end - - it 'should get the correct entry (string)' do - @timeout = 10 - @key = 'some_key' - @data = 'Hello World !' - @expected = @data - end - - it 'should not write the entry' do - @timeout = 0 - @key = 'another_key' - @data = 'Another Hello World !' - @expected = nil - end - - ## TODO write / read for an object - end - - describe '#storage_dir' do - it 'should create a unique storage dir' do - storage_dirs = [] - - (1..5).each do |_| - storage_dirs << CacheFileStore.new(cache_dir).storage_path - end - - expect(storage_dirs.uniq.size).to eq 5 - end - end -end diff --git a/spec/lib/common/collections/wp_items_spec.rb b/spec/lib/common/collections/wp_items_spec.rb deleted file mode 100644 index a1c7414a..00000000 --- a/spec/lib/common/collections/wp_items_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -#encoding: UTF-8 - -require 'spec_helper' - -describe WpItems do - it_behaves_like 'WpItems::Detectable' do - subject(:wp_items) { WpItems } - let(:item_class) { WpItem } - let(:fixtures_dir) { COLLECTIONS_FIXTURES + '/wp_items/detectable' } - - let(:expected) do - { - request_params: { cache_ttl: 0, followlocation: true }, - targets_items_from_file: [ WpItem.new(uri, name: 'item1'), - WpItem.new(uri, name: 'item-2'), - WpItem.new(uri, name: 'mr-smith')], - - vulnerable_targets_items: [ WpItem.new(uri, name: 'mr-smith'), - WpItem.new(uri, name: 'neo')], - - passive_detection: (1..15).reduce(WpItems.new) { |o, i| o << WpItem.new(uri, name: "detect-me-#{i}") } - } - end - end -end diff --git a/spec/lib/common/collections/wp_plugins/detectable_spec.rb b/spec/lib/common/collections/wp_plugins/detectable_spec.rb deleted file mode 100644 index cc3be4fc..00000000 --- a/spec/lib/common/collections/wp_plugins/detectable_spec.rb +++ /dev/null @@ -1,116 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' -require WPSCAN_LIB_DIR + '/wp_target' - -describe 'WpPlugins::Detectable' do - subject(:wp_plugins) { WpPlugins } - let(:wp_content_dir) { 'wp-content' } - let(:wp_plugins_dir) { wp_content_dir + '/plugins' } - let(:wp_target) { WpTarget.new(url, wp_content_dir: wp_content_dir, wp_plugins_dir: wp_plugins_dir) } - let(:url) { 'http://example.com/' } - let(:uri) { URI.parse(url) } - - describe '::from_header' do - context 'when no header' do - it 'returns an empty WpPlugins' do - stub_request(:get, url).to_return(status: 200) - expect(subject.send(:from_header, wp_target)).to eq subject.new - end - end - - context 'when headers' do - let(:headers) { { } } - let(:expected) { subject.new(wp_target) } - - after :each do - stub_request(:get, url).to_return(status: 200, headers: headers, body: '') - expect(subject.send(:from_header, wp_target)).to eq expected - end - - context 'when w3-total-cache detected' do - it 'returns the w3-total-cache' do - headers['X-Powered-BY'] = 'W3 Total Cache/0.9' - expected.add('w3-total-cache', version: '0.9') - end - end - - context 'when wp-super-cache detected' do - it 'returns the wp-super-cache' do - headers['WP-Super-Cache'] = 'Served supercache file from PHP' - expected.add('wp-super-cache') - end - end - - context 'when a header key with mutiple values' do - let(:headers) { { 'X-Powered-BY' => ['PHP/5.4.9', 'ASP.NET'] } } - - context 'when no cache plugin' do - it 'returns an empty WpPlugins' do - # Handled - end - end - - context 'when a cache plugin' do - it 'returns the correct plugin' do - headers['X-Powered-BY'] << 'W3 Total Cache/0.9.2.5' - - expected.add('w3-total-cache', version: '0.9.2.5') - end - end - end - end - end - - describe '::from_content' do - context 'when no body' do - it 'returns an empty WpPlugins' do - stub_request(:get, url).to_return(status: 200, body: '') - expect(subject.send(:from_content, wp_target)).to eq subject.new - end - end - - context 'when body' do - @body = '' - let(:expected) { subject.new(wp_target) } - - after :each do - stub_request(:get, url).to_return(status: 200, body: @body) - stub_request(:get, /readme\.txt/i).to_return(status: 404) - expect(subject.send(:from_content, wp_target)).to eq expected - end - - context 'when w3 total cache detected' do - it 'returns the w3-total-cache' do - @body = 'w3 total cache' - expected.add('w3-total-cache') - end - end - - context 'when wp-super-cache detected' do - it 'returns the wp-super-cache' do - @body = 'wp-super-cache' - expected.add('wp-super-cache') - end - end - - context 'when all-in-one-seo-pack detected' do - it 'returns the all-in-one-seo-pack' do - @body = '' - expected.add('all-in-one-seo-pack', version: '2.0.3.1') - end - end - - context 'when google-universal-analytics detected' do - it 'returns google-universal-analytics' do - @body = '' - expected.add('google-universal-analytics', version: '2.4.2') - end - end - end - end - - describe '::passive_detection' do - # TODO - end -end diff --git a/spec/lib/common/collections/wp_plugins_spec.rb b/spec/lib/common/collections/wp_plugins_spec.rb deleted file mode 100644 index 5b0a1804..00000000 --- a/spec/lib/common/collections/wp_plugins_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -#encoding: UTF-8 - -require 'spec_helper' - -describe WpPlugins do - it_behaves_like 'WpItems::Detectable' do - subject(:wp_plugins) { WpPlugins } - let(:item_class) { WpPlugin } - let(:fixtures_dir) { COLLECTIONS_FIXTURES + '/wp_plugins/detectable' } - - let(:expected) do - { - request_params: { cache_ttl: 0, followlocation: true }, - vulns_file: PLUGINS_FILE, - targets_items_from_file: [ WpPlugin.new(uri, name: 'plugin1'), - WpPlugin.new(uri, name:'plugin-2'), - WpPlugin.new(uri, name: 'mr-smith')], - - vulnerable_targets_items: [ WpPlugin.new(uri, name: 'mr-smith'), - WpPlugin.new(uri, name: 'neo')], - - passive_detection: WpPlugins.new << WpPlugin.new(uri, name: 'escaped-url') << - WpPlugin.new(uri, name: 'link-tag') << - WpPlugin.new(uri, name: 'script-tag') << - WpPlugin.new(uri, name: 'style-tag') << - WpPlugin.new(uri, name: 'style-tag-import') - } - end - end -end diff --git a/spec/lib/common/collections/wp_themes_spec.rb b/spec/lib/common/collections/wp_themes_spec.rb deleted file mode 100644 index b29c56ec..00000000 --- a/spec/lib/common/collections/wp_themes_spec.rb +++ /dev/null @@ -1,31 +0,0 @@ -#encoding: UTF-8 - -require 'spec_helper' - -describe WpThemes do - before { stub_request(:get, /.+\/style.css$/).to_return(status: 200) } - - it_behaves_like 'WpItems::Detectable' do - subject(:wp_themes) { WpThemes } - let(:item_class) { WpTheme } - let(:fixtures_dir) { COLLECTIONS_FIXTURES + '/wp_themes/detectable' } - - let(:expected) do - { - request_params: { cache_ttl: 0, followlocation: true }, - vulns_file: THEMES_FILE, - targets_items_from_file: [ WpTheme.new(uri, name: '3colours'), - WpTheme.new(uri, name:'42k'), - WpTheme.new(uri, name: 'a-ri')], - - vulnerable_targets_items: [ WpTheme.new(uri, name: 'shopperpress'), - WpTheme.new(uri, name: 'webfolio')], - - passive_detection: WpThemes.new << WpTheme.new(uri, name: 'theme1') << - WpTheme.new(uri, name: 'theme 2') << - WpTheme.new(uri, name: 'theme-3') << - WpTheme.new(uri, name: 'style-tag-import') - } - end - end -end diff --git a/spec/lib/common/collections/wp_timthumbs/detectable_spec.rb b/spec/lib/common/collections/wp_timthumbs/detectable_spec.rb deleted file mode 100644 index 96e7b1fd..00000000 --- a/spec/lib/common/collections/wp_timthumbs/detectable_spec.rb +++ /dev/null @@ -1,123 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' -require WPSCAN_LIB_DIR + '/wp_target' - -describe 'WpTimthumbs::Detectable' do - subject(:wp_timthumbs) { WpTimthumbs } - let(:fixtures_dir) { COLLECTIONS_FIXTURES + '/wp_timthumbs/detectable' } - let(:targets_items_file) { fixtures_dir + '/targets.txt' } - let(:wp_content_dir) { 'wp-content' } - let(:wp_plugins_dir) { wp_content_dir + '/plugins' } - let(:wp_target) { WpTarget.new(url, wp_content_dir: wp_content_dir, wp_plugins_dir: wp_plugins_dir) } - let(:url) { 'http://example.com/' } - let(:uri) { URI.parse(url) } - let(:empty_file) { SPEC_FIXTURES_DIR + '/empty-file' } - - let(:expected) do - { - targets_from_file: [WpTimthumb.new(uri, path: 'timthumb.php'), - WpTimthumb.new(uri, path: '$wp-content$/timthumb.php'), - WpTimthumb.new(uri, path: '$wp-plugins$/a-gallery/timthumb.php'), - WpTimthumb.new(uri, path: '$wp-content$/themes/theme-name/timthumb.php')] - - } - end - - def expected_targets_from_theme(theme_name) - expected = [] - %w( - timthumb.php lib/timthumb.php inc/timthumb.php includes/timthumb.php - scripts/timthumb.php tools/timthumb.php functions/timthumb.php thumb.php - ).each do |file| - path = "$wp-content$/themes/#{theme_name}/#{file}" - expected << WpTimthumb.new(uri, path: path) - end - expected - end - - describe '::passive_detection' do - it 'returns an empty WpTimthumbs' do - expect(subject.passive_detection(wp_target)).to eq subject.new - end - end - - describe '::targets_items_from_file' do - after do - targets = subject.send(:targets_items_from_file, file, wp_target) - - expect(targets.map(&:url)).to eq @expected.map(&:url) - end - - context 'when an empty file' do - let(:file) { empty_file } - - it 'returns an empty Array' do - @expected = [] - end - end - - context 'when a non empty file' do - let(:file) { targets_items_file } - - it 'returns the correct Array of WpTimthumb' do - @expected = expected[:targets_from_file] - end - end - end - - describe '::theme_timthumbs' do - it 'returns the correct Array of WpTimthumb' do - theme = 'hello-world' - targets = subject.send(:theme_timthumbs, theme, wp_target) - - expect(targets.map(&:url)).to eq expected_targets_from_theme(theme).map(&:url) - end - end - - describe '::targets_items' do - let(:options) { {} } - - after do - targets = subject.send(:targets_items, wp_target, options) - - expect(targets.map(&:url)).to match_array(@expected.map(&:url)) - end - - context 'when no :theme_name' do - context 'when no :file' do - it 'returns an empty Array' do - @expected = [] - end - end - - context 'when :file' do - let(:options) { { file: targets_items_file } } - - it 'returns the targets from the file' do - @expected = expected[:targets_from_file] - end - end - end - - context 'when :theme_name' do - let(:theme) { 'theme-name' } - - context 'when no :file' do - let(:options) { { theme_name: theme } } - - it 'returns targets from the theme' do - @expected = expected_targets_from_theme(theme) - end - end - - context 'when :file' do - let(:options) { { theme_name: theme, file: targets_items_file } } - - it 'returns merged targets from theme and file' do - @expected = (expected_targets_from_theme('theme-name') + expected[:targets_from_file]).uniq { |i| i.url } - end - end - end - end -end diff --git a/spec/lib/common/collections/wp_users/detectable_spec.rb b/spec/lib/common/collections/wp_users/detectable_spec.rb deleted file mode 100644 index 3a8c0f3b..00000000 --- a/spec/lib/common/collections/wp_users/detectable_spec.rb +++ /dev/null @@ -1,59 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' -require WPSCAN_LIB_DIR + '/wp_target' - -describe 'WpUsers::Detectable' do - subject(:wp_users) { WpUsers } - let(:wp_content_dir) { 'wp-content' } - let(:wp_plugins_dir) { wp_content_dir + '/plugins' } - let(:wp_target) { WpTarget.new(url, wp_content_dir: wp_content_dir, wp_plugins_dir: wp_plugins_dir) } - let(:url) { 'http://example.com/' } - let(:uri) { URI.parse(url) } - - def create_from_range(range) - result = [] - - range.each do |current_id| - result << WpUser.new(uri, id: current_id) - end - result - end - - describe '::request_params' do - it 'return an empty Hash' do - expect(subject.request_params).to be === {} - end - end - - describe '::passive_detection' do - it 'return an empty WpUsers' do - expect(subject.passive_detection(wp_target)).to eq subject.new - end - end - - describe '::targets_items' do - after do - targets = subject.send(:targets_items, wp_target, options) - - expect(targets).to eq @expected - end - - context 'when no :range' do - let(:options) { {} } - - it 'returns Array with id from 1 to 10' do - @expected = create_from_range((1..10)) - end - end - - context 'when :range' do - let(:options) { { range: (1..2) } } - - it 'returns Array with id from 1 to 2' do - @expected = create_from_range((1..2)) - end - end - end - -end diff --git a/spec/lib/common/collections/wp_users/output_spec.rb b/spec/lib/common/collections/wp_users/output_spec.rb deleted file mode 100644 index 1873d960..00000000 --- a/spec/lib/common/collections/wp_users/output_spec.rb +++ /dev/null @@ -1,86 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe 'WpUsers::Output' do - subject(:wp_users) { WpUsers.new(0) } - let(:wp_content_dir) { 'wp-content' } - let(:wp_plugins_dir) { wp_content_dir + '/plugins' } - let(:wp_target) { WpTarget.new(url, wp_content_dir: wp_content_dir, wp_plugins_dir: wp_plugins_dir) } - let(:url) { 'http://example.com/' } - let(:uri) { URI.parse(url) } - - describe '#remove_junk_from_display_names' do - it 'does not throw an exception' do - expect { subject.remove_junk_from_display_names }.to_not raise_error - end - end - - describe '#remove_junk_from_display_names' do - before :each do - @input = WpUsers.new(0) - end - - after :each do - subject.push(@input) - subject.flatten! - subject.remove_junk_from_display_names - expect(subject).to eq @expected - end - - it 'returns an empty array' do - @expected = @input - end - - it 'returns input object' do - @input.push(WpUser.new(nil)) - @expected = @input - end - - it 'returns input object' do - @input.push(WpUser.new('')) - @expected = @input - end - - it 'should remove asdf' do - @input.push(WpUser.new('', login: '', id: 1, display_name: 'lkjh asdf')) - @input.push(WpUser.new('', login: '', id: 2, display_name: 'ijrjd asdf')) - @expected = WpUsers.new(0) - @expected.push(WpUser.new('', login: '', id: 1, display_name: 'lkjh')) - @expected.push(WpUser.new('', login: '', id: 2, display_name: 'ijrjd')) - end - - it 'returns unmodified input object' do - @input.push(WpUser.new('', login: '', id: 1, display_name: 'lkjh asdfa')) - @input.push(WpUser.new('', login: '', id: 2, display_name: 'ijrjd asdf')) - @expected = @input - end - - it 'returns input object' do - @input.push(WpUser.new('', login: '', id: 1, display_name: 'lkjh asdf')) - @expected = @input - end - - it 'returns an empty display_name' do - @input.push(WpUser.new('', login: '', id: 1, display_name: 'lkhj asdf')) - @input.push(WpUser.new('', login: '', id: 2, display_name: 'lkhj asdf')) - @expected = WpUsers.new(0) - @expected.push(WpUser.new('', login: '', id: 1, display_name: '')) - @expected.push(WpUser.new('', login: '', id: 2, display_name: '')) - end - - context 'when a user has no display_name' do - it 'returns an empty display_name' do - @input.push(WpUser.new('', login: '', id: 1, display_name: 'lkhj asdf')) - @input.push(WpUser.new('', login: '', id: 2, display_name: 'lkhj asdf')) - @input.push(WpUser.new('', login: '', id: 3)) - - @expected = WpUsers.new(0) - - (1..3).each do |id| - @expected.push(WpUser.new('', login: '', id: id, display_name: '')) - end - end - end - end -end diff --git a/spec/lib/common/collections/wp_users_spec.rb b/spec/lib/common/collections/wp_users_spec.rb deleted file mode 100644 index 8ff740dd..00000000 --- a/spec/lib/common/collections/wp_users_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe WpUsers do - it_behaves_like 'WpUsers::BruteForcable' - - subject(:wp_users) { WpUsers.new } - let(:url) { 'http://example.com/' } - let(:uri) { URI.parse(url) } -end diff --git a/spec/lib/common/common_helper_spec.rb b/spec/lib/common/common_helper_spec.rb deleted file mode 100644 index 25b67977..00000000 --- a/spec/lib/common/common_helper_spec.rb +++ /dev/null @@ -1,170 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe 'common_helper' do - describe '#get_equal_string' do - after :each do - output = get_equal_string_end(@input) - - expect(output).to eq @expected - end - - it 'returns an empty string' do - @input = %w() - @expected = '' - end - - it 'returns an empty string' do - @input = [] - @expected = '' - end - - it 'returns an empty string' do - @input = ['asdf', nil] - @expected = '' - end - - it 'returns an empty string' do - @input = [nil, 'asdf'] - @expected = '' - end - - it 'returns asdf' do - @input = [nil, 'a asdf', nil, 'b asdf'] - @expected = ' asdf' - end - - it 'returns asdf' do - @input = ['kjh asdf', 'oijr asdf'] - @expected = ' asdf' - end - - it 'returns « BlogName' do - @input = ['user1 « BlogName', - 'user2 « BlogName', - 'user3 « BlogName', - 'user4 « BlogName'] - @expected = ' « BlogName' - end - - it 'returns an empty string' do - @input = %w{user1 user2 user3 user4} - @expected = '' - end - - it 'returns an empty string' do - @input = ['user1 « BlogName', - 'user2 « BlogName', - 'user3 « BlogName', - 'user4 « BlogNamea'] - @expected = '' - end - - it 'returns an empty string' do - @input = %w{ user1 } - @expected = '' - end - - it 'returns | test' do - @input = ['admin | test', 'test | test'] - @expected = ' | test' - end - end - - describe '#remove_base64_images_from_html' do - after :each do - output = remove_base64_images_from_html(@html) - expect(output).to eq @expected - end - - it 'removes the valid base64 image' do - @html = '' - @expected = '' - end - - it 'ignores invalid base64 content' do - @html = '' - @expected = @html - end - end - - describe '#truncate' do - after :each do - output = truncate(@input, @length, @trailing) - expect(output).to eq @expected - end - - it 'returns nil on no input' do - @input = nil - @length = 1 - @expected = nil - @trailing = '...' - end - - it 'returns input when length > input' do - @input = '1234567890' - @length = 13 - @expected = @input - @trailing = '...' - end - - it 'truncates the input' do - @input = '1234567890' - @length = 6 - @expected = '123...' - @trailing = '...' - end - - it 'adds own trailing' do - @input = '1234567890' - @length = 7 - @expected = '123xxxx' - @trailing = 'xxxx' - end - - it 'accepts strings as length' do - @input = '1234567890' - @length = '6' - @expected = '123...' - @trailing = '...' - end - - it 'checks if trailing is longer than input' do - @input = '1234567890' - @length = 1 - @expected = @input - @trailing = 'A' * 20 - end - - it 'returns input on negative length' do - @input = '1234567890' - @length = -1 - @expected = @input - @trailing = '...' - end - - it 'returns input on length == input.length' do - @input = '1234567890' - @length = '10' - @expected = @input - @trailing = '...' - end - - it 'returns cut string on nil trailing' do - @input = '1234567890' - @length = 9 - @expected = '123456789' - @trailing = nil - end - - it 'trailing.length > length' do - @input = '1234567890' - @length = 1 - @expected = @input - @trailing = 'A' * 20 - end - - end - -end diff --git a/spec/lib/common/custom_option_parser_spec.rb b/spec/lib/common/custom_option_parser_spec.rb deleted file mode 100644 index a8752638..00000000 --- a/spec/lib/common/custom_option_parser_spec.rb +++ /dev/null @@ -1,155 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe CustomOptionParser do - - let(:parser) { CustomOptionParser.new } - - describe '#new' do - - end - - describe '::option_to_symbol' do - after :each do - if @exception - expect { CustomOptionParser::option_to_symbol(@option) }.to raise_error(@exception) - else - expect(CustomOptionParser::option_to_symbol(@option)).to be === @expected - end - end - - context 'without REQUIRED or OPTIONAL arguments' do - context 'with short option' do - it 'should return :test' do - @option = ['-t', '--test', 'Testing'] - @expected = :test - end - - it 'should :its_a_long_option' do - @option = ['-l', '--its-a-long-option', "Testing '-' replacement"] - @expected = :its_a_long_option - end - end - - context 'without short option' do - it 'should return :long' do - @option = ['--long', "The method should find the option name ('long')"] - @expected = :long - end - - it 'should return :long_option' do - @option = ['--long-option', 'No short !'] - @expected = :long_option - end - end - - context 'without long option' do - it 'should raise an arror' do - @option = ['-v', 'The long option is missing there'] - @exception = 'Could not find the option name for ["-v", "The long option is missing there"]' - end - - it 'should raise an error' do - @option = ['The long option is missing there'] - @exception = 'Could not find the option name for ["The long option is missing there"]' - end - end - - context 'with multiple long option names (like alias)' do - it 'should return :check_long and not :cl' do - @option = ['--check-long', '--cl'] - @expected = :check_long - end - end - end - - context 'with REQUIRED or OPTIONAL arguments' do - it 'should removed the OPTIONAL argument' do - @option = ['-p', '--page [PAGE_NUMBER]'] - @expected = :page - end - - it 'should removed the REQUIRED argument' do - @option = ['--url TARGET_URL'] - @expected = :url - end - end - - end - - describe '#add_option' do - context 'exception throwing if' do - after :each do - expect { parser.add_option(@option) }.to raise_error(@exception) - end - - it 'argument passed is not an Array' do - @option = 'a simple String' - @exception = "The option must be an array, String supplied : 'a simple String'" - end - - it 'option name is already used' do - @option = ['-v', '--verbose', 'Verbose mode'] - parser.add_option(@option) - @exception = 'The option verbose is already used !' - end - end - - it 'should have had 2 symbols (:verbose, :url) to @symbols_used' do - parser.add_option(['-v', '--verbose']) - parser.add_option(['--url TARGET_URL']) - - expect(parser.symbols_used.sort).to be === [:url, :verbose] - end - - context 'parsing' do - before :each do - parser.add_option(['-u', '--url TARGET_URL', 'Set the target url']) - end - - it 'should raise an error if an unknown option is supplied' do - expect { parser.parse!(['--verbose']) }.to raise_error(OptionParser::InvalidOption) - end - - it 'should raise an error if an option require an argument which is not supplied' do - expect { parser.parse!(['--url']) }.to raise_error(OptionParser::MissingArgument) - end - - it 'should retrieve the correct argument' do - parser.parse!(['-u', 'iam_the_target']) - expect(parser.results).to be === { url: 'iam_the_target' } - end - end - end - - describe '#add' do - it 'should raise an error if the argument is not an Array or Array(Array)' do - expect { parser.add('Hello') }.to raise_error('Options must be at least an Array, or an Array(Array). String supplied') - end - - before :each do - parser.add(['-u', '--url TARGET_URL']) - end - - context 'single option' do - it 'should add the :url option, and retrieve the correct argument' do - expect(parser.symbols_used).to be === [:url] - expect(parser.results(['-u', 'target.com'])).to be === { url: 'target.com' } - end - end - - context 'multiple options' do - it 'should add 2 options, and retrieve the correct arguments' do - parser.add([ - ['-v', '--verbose'], - ['--test [TEST_NUMBER]'] - ]) - - expect(parser.symbols_used.sort).to be === [:test, :url, :verbose] - expect(parser.results(['-u', 'wp.com', '-v', '--test'])).to be === { test: nil, url: 'wp.com', verbose: true } - end - end - end - -end diff --git a/spec/lib/common/models/vulnerability/output_spec.rb b/spec/lib/common/models/vulnerability/output_spec.rb deleted file mode 100644 index 7b339ebb..00000000 --- a/spec/lib/common/models/vulnerability/output_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe Vulnerability::Output do - - describe '#output' do - # How to test it ? oO - end - -end diff --git a/spec/lib/common/models/vulnerability_spec.rb b/spec/lib/common/models/vulnerability_spec.rb deleted file mode 100644 index 2d6bf039..00000000 --- a/spec/lib/common/models/vulnerability_spec.rb +++ /dev/null @@ -1,55 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe Vulnerability do - - describe '#new' do - subject(:vulnerability) { Vulnerability.new(title, type, references, fixed_version) } - let(:title) { 'A vulnerability title' } - let(:type) { 'XSS' } - let(:references) { {:url => 'example.com', :metasploit => 'm', :exploitdb => 'e'} } - - context 'w/o metasploit and fixed version modules argument' do - subject(:vulnerability) { Vulnerability.new(title, type, references) } - - its(:title) { should be title } - its(:references) { should be references } - its(:type) { should be type } - its(:fixed_in) { should be_empty } - end - - context 'with fixed version argument' do - let(:fixed_version) { '1.0' } - - its(:title) { should be title } - its(:references) { should be references } - its(:type) { should be type } - its(:fixed_in) { should be fixed_version } - end - - end - - describe '::load_from_json_item' do - subject(:vulnerability) { Vulnerability.load_from_json_item(item) } - let(:item) { - json(MODELS_FIXTURES + '/vulnerability/json_item.json') - } - - expected_refs = { - 'id' => ['3911'], - 'url' => ['Ref 1,Ref 2'], - 'cve' => ['2011-001'], - 'secunia' => ['secunia'], - 'osvdb' => ['osvdb'], - 'metasploit' => ['exploit/ex1'], - 'exploitdb' => ['exploitdb'] - } - - its(:title) { should == 'Vuln Title' } - its(:type) { should == 'CSRF' } - its(:references) { should == expected_refs} - its(:fixed_in) { should == '1.0'} - end - -end diff --git a/spec/lib/common/models/wp_item_spec.rb b/spec/lib/common/models/wp_item_spec.rb deleted file mode 100644 index ed33df30..00000000 --- a/spec/lib/common/models/wp_item_spec.rb +++ /dev/null @@ -1,166 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe WpItem do - it_behaves_like 'WpItem::Existable' - it_behaves_like 'WpItem::Findable#Found_From=' - it_behaves_like 'WpItem::Infos' do - let(:changelog_url) { uri.merge('changelog.txt').to_s } - let(:error_log_url) { uri.merge('error_log').to_s } - end - it_behaves_like 'WpItem::Versionable' - it_behaves_like 'WpItem::Vulnerable' do - let(:db_file) { MODELS_FIXTURES + '/wp_item/vulnerable/items_vulns.json' } - let(:identifier) { 'neo' } - let(:expected_refs) { { - 'id' => [2993], - 'url' => ['Ref 1', 'Ref 2'], - 'cve' => ['2011-001'], - 'secunia' => ['secunia'], - 'osvdb' => ['osvdb'], - 'metasploit' => ['exploit/ex1'], - 'exploitdb' => ['exploitdb'] - } } - let(:expected_vulns) { Vulnerabilities.new(1, Vulnerability.new("I'm the one", 'XSS', expected_refs)) } - end - - subject(:wp_item) { WpItem.new(uri, options) } - let(:uri) { URI.parse('http://example.com') } - let(:options) { {} } - - describe '#new' do - context 'with no options' do - its(:wp_content_dir) { is_expected.to eq 'wp-content' } - its(:wp_plugins_dir) { is_expected.to eq 'wp-content/plugins' } - its(:uri) { is_expected.to be uri } - end - - context 'with :wp_content_dir' do - let(:options) { { wp_content_dir: 'custom' } } - - its(:wp_content_dir) { is_expected.to eq 'custom' } - its(:wp_plugins_dir) { is_expected.to eq 'custom/plugins' } - end - - context 'with :wp_plugins_dir' do - let(:options) { { wp_plugins_dir: 'c-plugins' } } - - its(:wp_content_dir) { is_expected.to eq 'wp-content' } - its(:wp_plugins_dir) { is_expected.to eq 'c-plugins' } - end - end - - describe '#set_options' do - context 'no an allowed option' do - it 'ignores the option' do - expect(wp_item).not_to receive(:not_allowed=) - - wp_item.send(:set_options, { not_allowed: 'owned' }) - end - end - - context 'allowed option, w/o setter method' do - it 'raises an error' do - allow(wp_item).to receive(:allowed_options).and_return([:no_setter]) - - expect { - wp_item.send(:set_options, { no_setter: 'hello' }) - }.to raise_error('WpItem does not respond to no_setter=') - end - end - end - - describe '#path=' do - after do - wp_item.path = @path - expect(wp_item.path).to eq @expected - end - - context 'with default variable value' do - it 'replaces $wp-content$ by wp-content' do - @path = '$wp-content$/hello' - @expected = 'wp-content/hello' - end - - it 'replaces $wp-plugins$ by wp-content/plugins' do - @path = '$wp-plugins$/yolo/file.php' - @expected = 'wp-content/plugins/yolo/file.php' - end - end - - context 'whith custom variable values' do - before { - allow(wp_item).to receive(:wp_content_dir).and_return('custom-content') - allow(wp_item).to receive(:wp_plugins_dir).and_return('plugins') - } - - it 'replaces $wp-content$ by custom-content' do - @path = '$wp-content$/file.php' - @expected = 'custom-content/file.php' - end - - it 'replaces $wp-plugins$ by plugins' do - @path = '$wp-plugins$/readme.txt' - @expected = 'plugins/readme.txt' - end - end - end - - describe '#uri' do - context 'when the path is present' do - it 'returns it with the uri' do - path = 'somedir/somefile.php' - wp_item.path = path - - expect(wp_item.uri).to eq uri.merge(path) - end - end - end - - describe '#<=>' do - it 'bases the comparaison on the :name' do - wp_item.name = 'a-name' - other = WpItem.new(uri, name: 'other-name') - - expect(wp_item.<=>(other)).to be === 'a-name'.<=>('other-name') - end - end - - describe '#==' do - context 'when the :name is the same' do - it 'is ==' do - wp_item.name = 'some-name' - other = WpItem.new(uri, name: 'some-name') - - expect(wp_item).to eq other - end - end - - context 'otherwise' do - it 'is not ==' do - wp_item.name = 'Test' - other = WpItem.new(uri, name: 'hello') - - expect(wp_item).not_to eq other - end - end - end - - describe '#===' do - let(:options) { { name: 'a-name', version: '1.2' } } - - context 'when the :name and :version are the same' do - it 'is ===' do - expect(WpItem.new(uri, options)).to be === WpItem.new(uri.merge('yo'), options) - end - end - - context 'otherwise' do - it 'is not ===' do - expect(WpItem.new(uri, options)).not_to be === WpItem.new(uri, options.merge(version: '1.0')) - end - end - end - -end diff --git a/spec/lib/common/models/wp_plugin_spec.rb b/spec/lib/common/models/wp_plugin_spec.rb deleted file mode 100644 index bc88247c..00000000 --- a/spec/lib/common/models/wp_plugin_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe WpPlugin do - it_behaves_like 'WpPlugin::Vulnerable' - it_behaves_like 'WpItem::Vulnerable' do - let(:options) { { name: 'white-rabbit' } } - let(:db_file) { MODELS_FIXTURES + '/wp_plugin/vulnerable/plugins.json' } - let(:expected_refs) { { - 'id' => [2993], - 'url' => ['Ref 1', 'Ref 2'], - 'cve' => ['2011-001'], - 'secunia' => ['secunia'], - 'osvdb' => ['osvdb'], - 'metasploit' => ['exploit/ex1'], - 'exploitdb' => ['exploitdb'] - } } - let(:expected_vulns) { Vulnerabilities.new << Vulnerability.new('Follow me!', 'REDIRECT', expected_refs) } - end - - subject(:wp_plugin) { WpPlugin.new(uri, options) } - let(:uri) { URI.parse('http://example.com') } - let(:options) { { name: 'plugin-name' } } - - describe '#forge_uri' do - its('uri.to_s') { is_expected.to eq 'http://example.com/wp-content/plugins/plugin-name/' } - end - -end diff --git a/spec/lib/common/models/wp_theme/findable_spec.rb b/spec/lib/common/models/wp_theme/findable_spec.rb deleted file mode 100644 index 7251c477..00000000 --- a/spec/lib/common/models/wp_theme/findable_spec.rb +++ /dev/null @@ -1,164 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe 'WpTheme::Findable' do - let(:fixtures_dir) { MODELS_FIXTURES + '/wp_theme/findable' } - let(:uri) { URI.parse('http://example.com/') } - - describe '::find_from_css_link' do - before do - stub_request(:get, /.+\/style.css$/).to_return(status: 200) - end - - after do - @body ||= File.new(fixtures_dir + '/css_link/' + @file) - stub_request(:get, uri.to_s).to_return(status: 200, body: @body) - - wp_theme = WpTheme.send(:find_from_css_link, uri) - - expect(wp_theme).to be_a WpTheme if @expected - expect(wp_theme).to eq @expected - expect(wp_theme.wp_content_dir).to eql 'wp-content' if @expected - end - - context 'when theme is not present' do - it 'returns nil' do - @body = '' - @expected = nil - end - end - - context 'when the theme name has spaces or special chars' do - it 'returns the WpTheme' do - @file = 'theme-name-with-spaces.html' - @expected = WpTheme.new(uri, name: 'Copia di simplefolio') - end - end - - context 'when is inline' do - it 'returns the WpTheme' do - @file = 'inline_link_tag.html' - @expected = WpTheme.new(uri, name: 'inline') - end - end - - # FIXME: the style_url should be checked in WpTheme for absolute / relative - context 'when relative url is used' do - context 'when leading slash' do - it 'returns the WpTheme' do - @file = 'relative_urls.html' - @expected = WpTheme.new(uri, name: 'theme_name') - end - end - - context 'when no leading slash' do - it 'returns the WpTheme' do - @file = 'relative_urls_missing_slash.html' - @expected = WpTheme.new(uri, name: 'theme_name') - end - end - end - - context 'when other style.css is referenced' do - it 'returns the WpTheme' do - @file = 'yootheme.html' - @expected = WpTheme.new(uri, name: 'yoo_solar_wp', referenced_url: '/wp-content/themes/yoo_solar_wp/styles/wood/css/style.css') - end - end - - # This one might introduce FP btw - context 'when leaked from comments' do - it 'returns the WpTheme' do - @file = 'comments.html' - @expected = WpTheme.new(uri, name: 'debug') - end - end - end - - describe '::find_from_wooframework' do - before do - stub_request(:get, /.+\/style.css$/).to_return(status: 200) - end - - after do - @body ||= File.new(fixtures_dir + '/wooframework/' + @file) - stub_request(:get, uri.to_s).to_return(status: 200, body: @body) - - wp_theme = WpTheme.send(:find_from_wooframework, uri) - - if @expected - expect(wp_theme).to be_a WpTheme - end - expect(wp_theme).to eq @expected - end - - context 'when theme is not present' do - it 'returns nil' do - @body = '' - @expected = nil - end - end - - it 'returns the WpTheme' do - @file = 'merchant-no-version.html' - @expected = WpTheme.new(uri, name: 'Merchant') - end - - context 'when the version is present' do - it 'returns the WpTheme with it' do - @file = 'editorial-1.3.5.html' - @expected = WpTheme.new(uri, name: 'Editorial', version: '1.3.5') - end - end - end - - describe '::find' do - # Stub all WpTheme::find_from_* to return nil - def stub_all_to_nil - WpTheme.methods.grep(/^find_from_/).each do |method| - allow(WpTheme).to receive(method).and_return(nil) - end - end - - context 'when a method is named s_find_from_s' do - it 'does not call it' do - class WpTheme - module Findable - extend self - def s_find_from_s(s); raise 'I should not be called by ::find' end - end - end - - stub_all_to_nil - - expect { WpTheme.find(uri) }.to_not raise_error - end - end - - context 'when the theme is not found' do - it 'returns nil' do - stub_all_to_nil - - expect(WpTheme.find(uri)).to be_nil - end - end - - context 'when the theme is found' do - it 'returns it, with the :found_from set' do - stub_all_to_nil - stub_request(:get, /.+\/the-oracle\/style.css$/).to_return(status: 200) - expected = WpTheme.new(uri, name: 'the-oracle') - - allow(WpTheme).to receive(:find_from_css_link).and_return(expected) - wp_theme = WpTheme.find(uri) - - expect(wp_theme).to be_a WpTheme - expect(wp_theme).to eq expected - expect(wp_theme.found_from).to be === 'css link' - end - end - - end - -end diff --git a/spec/lib/common/models/wp_theme_spec.rb b/spec/lib/common/models/wp_theme_spec.rb deleted file mode 100644 index 2c7986e5..00000000 --- a/spec/lib/common/models/wp_theme_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe WpTheme do - it_behaves_like 'WpTheme::Versionable' - it_behaves_like 'WpTheme::Vulnerable' - it_behaves_like 'WpItem::Vulnerable' do - let(:options) { { name: 'the-oracle' } } - let(:db_file) { MODELS_FIXTURES + '/wp_theme/vulnerable/themes_vulns.json' } - let(:expected_refs) { { - 'id' => [2993], - 'url' => ['Ref 1', 'Ref 2'], - 'cve' => ['2011-001'], - 'secunia' => ['secunia'], - 'osvdb' => ['osvdb'], - 'metasploit' => ['exploit/ex1'], - 'exploitdb' => ['exploitdb'] - } } - let(:expected_vulns) { Vulnerabilities.new << Vulnerability.new('I see you', 'FPD', expected_refs) } - end - - subject(:wp_theme) { WpTheme.new(uri, options) } - let(:uri) { URI.parse('http://example.com/') } - let(:options) { { name: 'theme-name' } } - let(:theme_path) { 'wp-content/themes/theme-name/' } - - describe '#allowed_options' do - its(:allowed_options) { is_expected.to include :referenced_url } - end - - describe '#forge_uri' do - its(:uri) { is_expected.to eq uri.merge(theme_path) } - end - -end diff --git a/spec/lib/common/models/wp_timthumb_spec.rb b/spec/lib/common/models/wp_timthumb_spec.rb deleted file mode 100644 index a368bf38..00000000 --- a/spec/lib/common/models/wp_timthumb_spec.rb +++ /dev/null @@ -1,33 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe WpTimthumb do - it_behaves_like 'WpTimthumb::Existable' - it_behaves_like 'WpTimthumb::Versionable' - - subject(:wp_timthumb) { WpTimthumb.new(uri, options) } - let(:uri) { URI.parse('http://example.com/') } - let(:options) { { path: 'path-to/a/timtuhumb.php' } } - - describe '#==' do - context 'when both url are equal' do - it 'returns true' do - expect(WpTimthumb.new(uri, path: 'timtuhumb.php')). - to eq( - WpTimthumb.new(uri, path: 'timtuhumb.php') - ) - end - end - - context 'when urls are different' do - it 'returns false' do - expect(WpTimthumb.new(uri, path: 'hello/timtuhumb.php')). - not_to eq( - WpTimthumb.new(uri, path: 'some-dir/timtuhumb.php') - ) - end - end - end - -end diff --git a/spec/lib/common/models/wp_user_spec.rb b/spec/lib/common/models/wp_user_spec.rb deleted file mode 100644 index fdaf5be9..00000000 --- a/spec/lib/common/models/wp_user_spec.rb +++ /dev/null @@ -1,88 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe WpUser do - it_behaves_like 'WpUser::Existable' - it_behaves_like 'WpUser::BruteForcable' - - subject(:wp_user) { WpUser.new(uri, options) } - let(:uri) { URI.parse('http://example.com') } - let(:options) { {} } - - describe '#allowed_options' do - [:id, :login, :display_name, :password].each do |sym| - its(:allowed_options) { is_expected.to include sym } - end - - its(:allowed_options) { is_expected.not_to include :name } - end - - describe '#uri' do - context 'when the id is not set' do - it 'raises an error' do - expect { wp_user.uri }.to raise_error('The id is nil') - end - end - - context 'when the id is set' do - it 'returns the uri to the auhor page' do - wp_user.id = 2 - - expect(wp_user.uri).to eq uri.merge('?author=2') - end - end - end - - describe '#to_s' do - after do - subject.id = 1 - expect(subject.to_s).to eq @expected - end - - it 'returns @id' do - @expected = '1' - end - - context 'when @login' do - it 'returns @id | @login' do - subject.login = 'admin' - - @expected = '1 | admin' - end - - context 'when @display_name' do - it 'returns @id | @login | @display_name' do - subject.login = 'admin' - subject.display_name = 'real name' - - @expected = '1 | admin | real name' - end - end - end - end - - describe '#<=>' do - it 'bases the comparaison on the :id' do - wp_user.id = 1 - other = WpUser.new(uri, id: 3) - - expect(wp_user.<=>(other)).to be === 1.<=>(3) - end - end - - describe '#===, #==' do - context 'when the :id and :login are the same' do - it 'is ===, and ==' do - expect(WpUser.new(uri, id: 1, name: 'yo')).to eq WpUser.new(uri, id: 1, name: 'yo') - end - end - - context 'when :id and :login are different' do - it 'is not === or ==' do - expect(WpUser.new(uri, id: 1, name: 'yo')).not_to eq WpUser.new(uri, id: 2, name:'yo') - end - end - end - -end diff --git a/spec/lib/common/models/wp_version/findable_spec.rb b/spec/lib/common/models/wp_version/findable_spec.rb deleted file mode 100644 index 3ff0e0c5..00000000 --- a/spec/lib/common/models/wp_version/findable_spec.rb +++ /dev/null @@ -1,232 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe 'WpVersion::Findable' do - let(:fixtures_dir) { MODELS_FIXTURES + '/wp_version/findable/' } - let(:uri) { URI.parse('http://example.com/') } - let(:generator_urls) { - { - rss_generator: uri.merge('feed/').to_s, - rdf_generator: uri.merge('feed/rdf/').to_s, - atom_generator: uri.merge('feed/atom/').to_s, - comments_rss_generator: uri.merge('comments/feed/').to_s, - sitemap_generator: uri.merge('sitemap.xml').to_s - } - } - - # Dynamic creation for all generator methods - WpVersion.methods.grep(/^find_from_.*_generator$/).each do |method| - dir_name = method.to_s[%r{^find_from_(.*)$}, 1] - - describe "::#{method}" do - let(:url) { generator_urls[dir_name.to_sym] || uri.to_s } - - after do - fixture = fixtures_dir + dir_name + @fixture - stub_request_to_fixture(url: url, fixture: fixture) - - expect(WpVersion.send(method, uri)).to eq @expected - end - - context 'when generator not found' do - it 'returns nil' do - @fixture = '/no_generator.html' - @expected = nil - end - end - - context 'when version not found' do - it 'returns nil' do - @fixture = '/no_version.html' - @expected = nil - end - end - - context 'when invalid version' do - it 'returns nil' do - @fixture = '/invalid_version.html' - @expected = nil - end - end - - it 'returns 3.3.2' do - @fixture = '/3.3.2.html' - @expected = '3.3.2' - end - - it 'returns 3.4-beta4' do - @fixture = '/3.4-beta4.html' - @expected = '3.4-beta4' - end - - if method == :find_from_meta_generator - it 'returns 3.5' do - @fixture = '/3.5_minified.html' - @expected = '3.5' - end - - it 'returns 3.5.1' do - @fixture = '/3.5.1_mobile.html' - @expected = '3.5.1' - end - end - - end - end - - describe '::find_from_advanced_fingerprinting' do - let(:fixture_dir) { fixtures_dir + 'advanced_fingerprinting/' } - let(:wp_content_dir) { 'wp-content' } - let(:wp_plugins_dir) { wp_content_dir + '/plugins' } - let(:versions_xml) { fixture_dir + 'wp_versions.xml' } - - after do - version = WpVersion.send( - :find_from_advanced_fingerprinting, - uri, wp_content_dir, wp_plugins_dir, versions_xml - ) - expect(version).to eq @expected - end - - context 'when' do - it 'returns nil' do - stub_request(:get, /.*/).to_return(status: 404, body: '') - @expected = nil - end - end - - it 'returns 3.2.1' do - stub_request_to_fixture( - url: uri.merge('wp-admin/js/wp-fullscreen.js').to_s, - fixture: fixture_dir + '3.2.1.js' - ) - - @expected = '3.2.1' - end - end - - describe '::find_from_readme' do - let(:url) { uri.merge('readme.html').to_s } - - after do - fixture = fixtures_dir + 'readme' + @fixture - stub_request_to_fixture(url: url, fixture: fixture) - - expect(WpVersion.send(:find_from_readme, uri)).to eq @expected - end - - context 'when version not found' do - it 'returns nil' do - @fixture = '/empty_version.html' - @expected = nil - end - end - - context 'when invalid version' do - it 'returns nil' do - @fixture = '/invalid_version.html' - @expected = nil - end - end - - it 'returns 3.3.2' do - @fixture = '/3.3.2.html' - @expected = '3.3.2' - end - - context 'when version >= 4.7' do - it 'returns nil' do - @fixture = '/4.7.2.html' - @expected = nil - end - end - end - - describe '::find_from_links_opml' do - let(:url) { uri.merge('wp-links-opml.php') } - - after do - fixture = fixtures_dir + 'links_opml' + @fixture - stub_request_to_fixture(url: url, fixture: fixture) - - expect(WpVersion.send(:find_from_links_opml, uri)).to eq @expected - end - - it 'returns 3.4.2' do - @fixture = '/3.4.2.xml' - @expected = '3.4.2' - end - - context 'when no generator' do - it 'returns nil' do - @fixture = '/no_generator.xml' - @expected = nil - end - end - end - - describe '::find_from_stylesheets_numbers' do - after do - fixture = fixtures_dir + 'stylesheet_numbers' + @fixture - stub_request_to_fixture(url: uri, fixture: fixture) - - expect(WpVersion.send(:find_from_stylesheets_numbers, uri)).to eq @expected - end - - context 'invalid url' do - it 'returns nil' do - @fixture = '/invalid_url.html' - @expected = nil - end - end - end - - describe '::find' do - # Stub all WpVersion::find_from_* to return nil - def stub_all_to_nil - WpVersion.methods.grep(/^find_from_/).each do |method| - allow(WpVersion).to receive(method).and_return(nil) - end - end - - let(:wp_content_dir) { 'wp-content' } - let(:wp_plugins_dir) { wp_content_dir + '/plugins' } - let(:version_xml) {} - - after do - stub_request(:get, /#{uri.to_s}.*/).to_return(status: 0) - - version = WpVersion.find(uri, wp_content_dir, wp_plugins_dir, version_xml) - expect(version).to eq @expected - if @expected - expect(version.found_from).to eq @found_from - end - end - - context 'when no version found' do - it 'returns nil' do - stub_all_to_nil - @expected = nil - end - end - - WpVersion.methods.grep(/^find_from_/).each do |method| - number = "#{rand(5)}.#{rand(3)}" - found_from = method[/^find_from_(.*)/, 1].sub('_', ' ') - - context "when found from #{found_from}" do - it 'returns the correct WpVersion' do - stub_all_to_nil - - allow(WpVersion).to receive(method).and_return(number) - - @expected = WpVersion.new(uri, number: number) - @found_from = found_from - end - end - end - - end - -end diff --git a/spec/lib/common/models/wp_version_spec.rb b/spec/lib/common/models/wp_version_spec.rb deleted file mode 100644 index 33a3e2c5..00000000 --- a/spec/lib/common/models/wp_version_spec.rb +++ /dev/null @@ -1,26 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe WpVersion do - it_behaves_like 'WpVersion::Vulnerable' - - subject(:wp_version) { WpVersion.new(uri, options) } - let(:uri) { URI.parse('http://example.com/') } - let(:options) { { number: '1.2' } } - - describe '#allowed_options' do - [:number, :found_from].each do |sym| - its(:allowed_options) { is_expected.to include sym } - end - end - - describe '#all' do - let(:versions_file) { File.join(MODELS_FIXTURES, 'wp_version', 'findable', 'advanced_fingerprinting', 'wp_versions.xml') } - - it 'returns the array containign the two versions' do - expect(WpVersion.all(versions_file)).to eq ['3.2.1', '3.2'] - end - end - -end diff --git a/spec/lib/common/plugins/plugin_spec.rb b/spec/lib/common/plugins/plugin_spec.rb deleted file mode 100644 index a7e7fd12..00000000 --- a/spec/lib/common/plugins/plugin_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe Plugin do - subject(:plugin) { Plugin.new } - - describe '#new' do - context 'with some infos' do - subject(:plugin) { Plugin.new(infos) } - let(:infos) { { author: 'John' } } - - its(:author) { is_expected.to be === infos[:author] } - end - end - - describe '#run' do - it 'should raise a NotImplementedError' do - expect { plugin.run }.to raise_error(NotImplementedError) - end - end - - describe '#register_options' do - after :each do - if @exception - expect { plugin.register_options(*@options) }.to raise_error(@exception) - else - plugin.register_options(*@options) - expect(plugin.registered_options.sort).to be === @expected.sort - end - end - - context 'when an option is not an Array' do - it 'should raise an error' do - @options = [ - ['-v', '--verbose', 'It\'s a valid option'], - 'Not a valid one' - ] - @exception = 'Each option must be an array, String supplied' - end - end - - context 'when options are Arrays' do - it 'should register the options' do - @options = [ - ['-v', '--verbose', 'Verbose mode'], - ['-u', '--url TARGET_URL'] - ] - @expected = *@options - end - end - end - -end diff --git a/spec/lib/common/plugins/plugins_spec.rb b/spec/lib/common/plugins/plugins_spec.rb deleted file mode 100644 index f86f7535..00000000 --- a/spec/lib/common/plugins/plugins_spec.rb +++ /dev/null @@ -1,97 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -class TestPlugin < Plugin - def initialize - register_options(['-u', '--url']) - end -end - -class AnotherPlugin < Plugin - def initialize - super(author: 'John') - # No Options - end -end - -describe Plugins do - subject(:plugins) { Plugins.new } - - let(:test_plugin) { TestPlugin.new } - let(:another_plugin) { AnotherPlugin.new } - - describe '#new' do - context 'without argument' do - its(:option_parser) { is_expected.to be_a CustomOptionParser } - - it 'should be an Array' do - expect(plugins).to be_an Array - end - end - - context 'with an option_parser argument' do - subject(:plugin) { Plugins.new(CustomOptionParser.new('the banner')) } - - its(:option_parser) { is_expected.to be_a CustomOptionParser } - its('option_parser.banner') { is_expected.to be === 'the banner' } - - it 'should raise an eror if the parser is not an instance of CustomOptionParser' do - expect { Plugins.new(OptionParser.new) }.to raise_error('The parser must be an instance of CustomOptionParser, OptionParser supplied') - end - end - end - - describe '#register_plugin' do - after :each do - if @exception - expect { plugins.register_plugin(@plugin) }.to raise_error(@exception) - else - plugins.register_plugin(@plugin) - expect(plugins).to include(@plugin) - expect(plugins).to be === @expected - end - end - - context 'when the argument supplied is not an instance of Plugin' do - it 'should raise an error' do - @plugin = "I'am a String" - @exception = 'The argument must be an instance of Plugin, String supplied' - end - end - - it 'should register the plugin' do - @plugin = TestPlugin.new - @expected = [@plugin] - end - - it 'should register 2 plugins (the order is important)' do - plugins.register_plugin(test_plugin) - - @plugin = another_plugin - @expected = [test_plugin, @plugin] - end - end - - describe '#register' do - after :each do - plugins.register(*@plugins_to_register) - - @plugins_to_register.each do |plugin| - expect(plugins).to include(plugin) - end - - # For the correct order - expect(plugins).to be === @plugins_to_register - end - - it 'should register 1 plugin' do - @plugins_to_register = [test_plugin] - end - - it 'should register 2 plugins' do - @plugins_to_register = [another_plugin, test_plugin] - end - end - -end diff --git a/spec/lib/common/typhoeus_cache_spec.rb b/spec/lib/common/typhoeus_cache_spec.rb deleted file mode 100644 index 32356a91..00000000 --- a/spec/lib/common/typhoeus_cache_spec.rb +++ /dev/null @@ -1,3 +0,0 @@ -# encoding: UTF-8 - -# TODO diff --git a/spec/lib/common/version_compare_spec.rb b/spec/lib/common/version_compare_spec.rb deleted file mode 100644 index f70de6ba..00000000 --- a/spec/lib/common/version_compare_spec.rb +++ /dev/null @@ -1,247 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe 'VersionCompare' do - describe '::lesser_or_equal?' do - context 'version checked is newer' do - after { expect(VersionCompare::lesser_or_equal?(@version1, @version2)).to be_truthy } - - it 'returns true' do - @version1 = '1.0' - @version2 = '2.0' - end - - it 'returns true' do - @version1 = '1.0' - @version2 = '1.1' - end - - it 'returns true' do - @version1 = '1.0a' - @version2 = '1.0b' - end - - it 'returns true' do - @version1 = '1.0' - @version2 = '5000000' - end - - it 'returns true' do - @version1 = '0' - @version2 = '1' - end - - it 'returns true' do - @version1 = '0.4.2b' - @version2 = '2.3.3' - end - - it 'returns true' do - @version1 = '.47' - @version2 = '.50.3' - end - end - - context 'version checked is older' do - after { expect(VersionCompare::lesser_or_equal?(@version1, @version2)).to be_falsey } - - it 'returns false' do - @version1 = '1' - @version2 = '0' - end - - it 'returns false' do - @version1 = '1.0' - @version2 = '0.5' - end - - it 'returns false' do - @version1 = '500000' - @version2 = '1' - end - - it 'returns false' do - @version1 = '1.6.3.7.3.4' - @version2 = '1.2.4.567.679.8.e' - end - - it 'returns false' do - @version1 = '.47' - @version2 = '.46.3' - end - end - - context 'version checked is the same' do - after { expect(VersionCompare::lesser_or_equal?(@version1, @version2)).to be_truthy } - - it 'returns true' do - @version1 = '1' - @version2 = '1' - end - - it 'returns true' do - @version1 = 'a' - @version2 = 'a' - end - - end - - context 'version number causes Gem::Version new Exception' do - after { expect(VersionCompare::lesser_or_equal?(@version1, @version2)).to be_falsey } - - it 'returns false' do - @version1 = 'a' - @version2 = 'b' - end - end - - context 'one version number is not set' do - after { expect(VersionCompare::lesser_or_equal?(@version1, @version2)).to be_falsey } - - it 'returns false (version2 nil)' do - @version1 = '1' - @version2 = nil - end - - it 'returns false (version1 nil)' do - @version1 = nil - @version2 = '1' - end - - it 'returns false (version2 empty)' do - @version1 = '1' - @version2 = '' - end - - it 'returns false (version1 empty)' do - @version1 = '' - @version2 = '1' - end - end - - end - - describe '::lesser?' do - context 'version checked is newer' do - after { expect(VersionCompare::lesser?(@version1, @version2)).to be_truthy } - - it 'returns true' do - @version1 = '1.0' - @version2 = '2.0' - end - - it 'returns true' do - @version1 = '1.0' - @version2 = '1.1' - end - - it 'returns true' do - @version1 = '1.0a' - @version2 = '1.0b' - end - - it 'returns true' do - @version1 = '1.0' - @version2 = '5000000' - end - - it 'returns true' do - @version1 = '0' - @version2 = '1' - end - - it 'returns true' do - @version1 = '0.4.2b' - @version2 = '2.3.3' - end - - it 'returns true' do - @version1 = '.47' - @version2 = '.50.3' - end - - it 'returns true' do - @version1 = '2.5.9' - @version2 = '2.5.10' - end - end - - context 'version checked is older' do - after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey } - - it 'returns false' do - @version1 = '1' - @version2 = '0' - end - - it 'returns false' do - @version1 = '1.0' - @version2 = '0.5' - end - - it 'returns false' do - @version1 = '500000' - @version2 = '1' - end - - it 'returns false' do - @version1 = '1.6.3.7.3.4' - @version2 = '1.2.4.567.679.8.e' - end - - it 'returns false' do - @version1 = '.47' - @version2 = '.46.3' - end - end - - context 'version checked is the same' do - after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey } - - it 'returns true' do - @version1 = '1' - @version2 = '1' - end - - it 'returns true' do - @version1 = 'a' - @version2 = 'a' - end - - end - - context 'version number causes Gem::Version new Exception' do - after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey } - - it 'returns false' do - @version1 = 'a' - @version2 = 'b' - end - end - - context 'one version number is not set' do - after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey } - - it 'returns false (version2 nil)' do - @version1 = '1' - @version2 = nil - end - - it 'returns false (version1 nil)' do - @version1 = nil - @version2 = '1' - end - - it 'returns false (version2 empty)' do - @version1 = '1' - @version2 = '' - end - - it 'returns false (version1 empty)' do - @version1 = '' - @version2 = '1' - end - end - end -end diff --git a/spec/lib/wpscan/web_site_spec.rb b/spec/lib/wpscan/web_site_spec.rb deleted file mode 100644 index 56b150b8..00000000 --- a/spec/lib/wpscan/web_site_spec.rb +++ /dev/null @@ -1,240 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe 'WebSite' do - let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WEB_SITE_DIR } - subject(:web_site) { WebSite.new('http://example.localhost/') } - - it_behaves_like 'WebSite::RobotsTxt' - it_behaves_like 'WebSite::InterestingHeaders' - - before :all do - Browser::reset - Browser.instance( - config_file: SPEC_FIXTURES_CONF_DIR + '/browser.conf.json', - cache_ttl: 0 - ) - end - - describe '#new' do - its(:url) { is_expected.to be === 'http://example.localhost/' } - end - - describe '#url=' do - after :each do - web_site.url = @uri - expect(web_site.url).to be === @expected - end - - context 'when protocol or trailing slash is missing' do - it 'should add them' do - @uri = 'example.localhost' - @expected = 'http://example.localhost/' - end - end - - context 'when there is a protocol or a trailing slash' do - it 'should not add them' do - @uri = 'http://example.localhost/' - @expected = @uri - end - end - end - - describe '#online?' do - it 'should not be considered online if the status code is 0' do - stub_request(:get, web_site.url).to_return(status: 0) - expect(web_site).not_to be_online - end - - it 'should be considered online if the status code is != 0' do - stub_request(:get, web_site.url).to_return(status: 200) - expect(web_site).to be_online - end - end - - describe '#has_basic_auth?' do - it 'should detect that the wpsite is basic auth protected' do - stub_request(:get, web_site.url).to_return(status: 401) - expect(web_site).to have_basic_auth - end - - it 'should not have a basic auth for a 200' do - stub_request(:get, web_site.url).to_return(status: 200) - expect(web_site).not_to have_basic_auth - end - end - - describe '#xml_rpc_url' do - it 'returns the xmlrpc url' do - expect(web_site.xml_rpc_url).to be === 'http://example.localhost/xmlrpc.php' - end - end - - describe '#has_xml_rpc?' do - it 'returns true' do - stub_request(:get, web_site.xml_rpc_url). - to_return(status: 200, body: 'XML-RPC server accepts POST requests only') - - expect(web_site).to have_xml_rpc - end - - it 'returns false' do - stub_request(:get, web_site.xml_rpc_url).to_return(status: 200) - expect(web_site).not_to have_xml_rpc - end - end - - describe '#redirection' do - it 'returns nil if no redirection detected' do - stub_request(:get, web_site.url).to_return(status: 200, body: '') - - expect(web_site.redirection).to be_nil - end - - [301, 302].each do |status_code| - it "returns http://new-location.com if the status code is #{status_code}" do - new_location = 'http://new-location.com' - - stub_request(:get, web_site.url). - to_return(status: status_code, headers: { location: new_location }) - - stub_request(:get, new_location).to_return(status: 200) - - expect(web_site.redirection).to be === 'http://new-location.com' - end - end - - context 'when relative URI in Location' do - it 'returns the absolute URI' do - relative_location = '/blog/' - absolute_location = web_site.uri.merge(relative_location).to_s - - stub_request(:get, web_site.url).to_return(status: 301, headers: { location: relative_location }) - stub_request(:get, absolute_location) - - expect(web_site.redirection).to eql absolute_location - end - - context 'when starts with a ?' do - it 'returns the absolute URI' do - relative_location = '?p=blog' - absolute_location = web_site.uri.merge(relative_location).to_s - - stub_request(:get, web_site.url).to_return(status: 301, headers: { location: relative_location }) - stub_request(:get, absolute_location) - - expect(web_site.redirection).to eql absolute_location - end - end - end - - context 'when multiple redirections' do - it 'returns the last redirection' do - first_redirection = 'http://www.redirection.com' - last_redirection = 'http://redirection.com' - - stub_request(:get, web_site.url).to_return(status: 301, headers: { location: first_redirection }) - stub_request(:get, first_redirection).to_return(status: 302, headers: { location: last_redirection }) - stub_request(:get, last_redirection).to_return(status: 200) - - expect(web_site.redirection).to be === last_redirection - end - end - end - - describe '#page_hash' do - after { expect(WebSite.page_hash(page)).to eq Digest::MD5.hexdigest(@expected) } - - context 'when the page is an url' do - let(:page) { 'http://e.localhost/somepage.php' } - - it 'returns the MD5 hash of the page' do - body = 'Hello World !' - stub_request(:get, page).to_return(body: body) - - @expected = body - end - end - - context 'when the page is a Typhoeus::Response' do - let(:page) { Typhoeus::Response.new(body: 'Hello Example!') } - - it 'returns the correct hash' do - @expected = 'Hello Example!' - end - end - - context 'when there are comments' do - let(:page) { - body = "yolo\n\n\nworld!" - Typhoeus::Response.new(body: body) - } - - it 'removes them' do - @expected = "yolo\n\n\nworld!" - end - end - - context 'when there are scripts' do - let(:page) { - body = "yolo\n\n\nworld!" - Typhoeus::Response.new(body: body) - } - - it 'removes them' do - @expected = "yolo\n\n\nworld!" - end - end - end - - describe '#homepage_hash' do - it 'returns the MD5 hash of the homepage' do - body = 'Hello World' - - stub_request(:get, web_site.url).to_return(body: body) - expect(web_site.homepage_hash).to be === Digest::MD5.hexdigest(body) - end - end - - describe '#error_404_hash' do - it 'returns the md5sum of the 404 page' do - stub_request(:any, /.*/). - to_return(status: 404, body: '404 page !') - - expect(web_site.error_404_hash).to be === Digest::MD5.hexdigest('404 page !') - end - end - - describe '::has_log?' do - let(:log_url) { web_site.uri.merge('log.txt').to_s } - let(:pattern) { %r{PHP Fatal error} } - - after do - stub_request_to_fixture(url: log_url, fixture: fixtures_dir + "/has_log/#{@file}") - expect(WebSite.has_log?(log_url, pattern)).to eq @expected - end - - context 'when the pattern does not match' do - it 'returns false' do - @file = 'no_match.txt' - @expected = false - end - end - - context 'when the pattern matches' do - it 'returns true' do - @file = 'matches.txt' - @expected = true - end - end - - # This doesn't work in rspec, WebMock or Typhoeus returns the whole file - # See https://github.com/bblimke/webmock/issues/277 - #it 'only checks the first 700 bytes' do - # @file = 'matches_after_700_bytes.txt' - # @expected = false - #end - end -end diff --git a/spec/lib/wpscan/wp_target_spec.rb b/spec/lib/wpscan/wp_target_spec.rb deleted file mode 100644 index 640fba5f..00000000 --- a/spec/lib/wpscan/wp_target_spec.rb +++ /dev/null @@ -1,218 +0,0 @@ -# encoding: UTF-8 - -require File.expand_path(File.join(__dir__, 'wpscan_helper')) - -describe WpTarget do - subject(:wp_target) { WpTarget.new(target_url, options) } - subject(:wp_target_custom) { WpTarget.new(target_url, options_custom) } - let(:target_url) { 'http://example.localhost/' } - let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR } - let(:login_url) { wp_target.uri.merge('wp-login.php').to_s } - let(:options) { - { - config_file: SPEC_FIXTURES_CONF_DIR + '/browser.conf.json', - cache_ttl: 0, - wp_content_dir: 'wp-content', - wp_plugins_dir: 'wp-content/plugins' - } - } - let(:options_custom) { - { - config_file: SPEC_FIXTURES_CONF_DIR + '/browser.conf.json', - cache_ttl: 0, - wp_content_dir: 'custom-content', - wp_plugins_dir: 'custom-content/plugins' - } - } - - before { Browser::reset } - - it_behaves_like 'WpTarget::WpReadme' - it_behaves_like 'WpTarget::WpRegistrable' - it_behaves_like 'WpTarget::WpConfigBackup' - it_behaves_like 'WpTarget::WpLoginProtection' - it_behaves_like 'WpTarget::WpCustomDirectories' - it_behaves_like 'WpTarget::WpFullPathDisclosure' - - describe '#initialize' do - it 'should raise an error if the target_url is nil or empty' do - expect { WpTarget.new(nil) }.to raise_error - expect { Wptarget.new('') }.to raise_error - end - end - - describe '#login_url' do - it 'returns the login url of the target' do - stub_request(:get, login_url).to_return(status: 200, body: '') - - expect(wp_target.login_url).to be === login_url - end - - it 'returns the redirection url if there is one (ie: for https)' do - https_login_url = login_url.gsub(/^http:/, 'https:') - - stub_request(:get, login_url).to_return(status: 302, headers: { location: https_login_url }) - stub_request(:get, https_login_url).to_return(status: 200) - - expect(wp_target.login_url).to be === https_login_url - end - end - - describe '#wordpress?' do - # each url (wp-login and xmlrpc) pointed to a 404 - before :each do - stub_request(:get, wp_target.url). - to_return(status: 200, body: '', headers: { 'X-Pingback' => wp_target.uri.merge('xmlrpc.php')}) - - # Preventing redirection check from login_url() - allow(wp_target).to receive_messages(redirection: nil) - - [wp_target.login_url, wp_target.xml_rpc_url].each do |url| - stub_request(:get, url).to_return(status: 404, body: '') - end - end - - it 'returns true if there is a /wp-content/ detected in the index page source' do - stub_request_to_fixture(url: wp_target.url, fixture: fixtures_dir + '/wp_content_dir/wordpress-3.4.1.htm') - - expect(wp_target).to be_wordpress - end - - it 'returns true if a custom content directory is detected' do - stub_request_to_fixture(url: wp_target_custom.url, fixture: fixtures_dir + '/wp_content_dir/wordpress-3.4.1-custom.htm') - expect(wp_target_custom).to be_wordpress - end - - it 'returns true if the xmlrpc is found' do - stub_request(:get, wp_target.xml_rpc_url). - to_return(status: 200, body: File.new(fixtures_dir + '/xmlrpc.php')) - - expect(wp_target).to be_wordpress - end - - it 'returns true if the wp-login is found and is a valid wordpress one' do - stub_request(:get, wp_target.login_url). - to_return(status: 200, body: File.new(fixtures_dir + '/wp-login.php')) - - expect(wp_target).to be_wordpress - end - - it 'returns false if both files are not found (404)' do - expect(wp_target).not_to be_wordpress - end - - context 'when the url contains "wordpress" and is a 404' do - let(:target_url) { 'http://lamp/wordpress-3.5./' } - - it 'returns false' do - stub_request(:get, wp_target.login_url).to_return(status: 404, body: 'The requested URL /wordpress-3.5. was not found on this server.') - - expect(wp_target).not_to be_wordpress - end - end - - context 'when the response is a 403' do - before { stub_request(:any, /.*/).to_return(status: 403) } - - it 'raises an error' do - expect { wp_target.wordpress? }.to raise_error - end - end - end - - describe '#wordpress_hosted?' do - it 'returns true if target url is a wordpress.com subdomain' do - target = WpTarget.new('http://test.wordpress.com/') - expect(target.wordpress_hosted?).to be_truthy - end - - it 'returns true if target url is a wordpress.com subdomain and has querystring' do - target = WpTarget.new('http://test.wordpress.com/path/file.php?a=b') - expect(target.wordpress_hosted?).to be_truthy - end - - it 'returns false if target url is not a wordpress.com subdomain' do - target = WpTarget.new('http://test.example.com/') - expect(target.wordpress_hosted?).to be_falsey - end - end - - describe '#debug_log_url' do - it "returns 'http://example.localhost/wp-content/debug.log" do - allow(wp_target).to receive_messages(wp_content_dir: 'wp-content') - expect(wp_target.debug_log_url).to be === 'http://example.localhost/wp-content/debug.log' - end - end - - describe '#has_debug_log?' do - let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/debug_log' } - - after :each do - allow(wp_target).to receive_messages(wp_content_dir: 'wp-content') - stub_request_to_fixture(url: wp_target.debug_log_url, fixture: @fixture) - expect(wp_target.has_debug_log?).to be === @expected - end - - it 'returns false' do - @fixture = SPEC_FIXTURES_DIR + '/empty-file' - @expected = false - end - - it 'returns true' do - @fixture = fixtures_dir + '/debug.log' - @expected = true - end - - it 'should also detect it if there are PHP notice' do - @fixture = fixtures_dir + '/debug-notice.log' - @expected = true - end - end - - describe '#search_replace_db_2_url' do - it 'returns the correct url' do - expect(wp_target.search_replace_db_2_url).to eq 'http://example.localhost/searchreplacedb2.php' - end - end - - describe '#search_replace_db_2_exists?' do - it 'returns true' do - stub_request(:any, wp_target.search_replace_db_2_url).to_return(status: 200, body: 'asdf by interconnect asdf') - expect(wp_target.search_replace_db_2_exists?).to be_truthy - end - - it 'returns false' do - stub_request(:any, wp_target.search_replace_db_2_url).to_return(status: 500) - expect(wp_target.search_replace_db_2_exists?).to be_falsey - end - - it 'returns false' do - stub_request(:any, wp_target.search_replace_db_2_url).to_return(status: 500, body: 'asdf by interconnect asdf') - expect(wp_target.search_replace_db_2_exists?).to be_falsey - end - end - - describe '#emergency_url' do - it 'returns the correct url' do - expect(wp_target.emergency_url).to eq 'http://example.localhost/emergency.php' - end - end - - describe '#emergency_exists?' do - it 'returns true' do - stub_request(:any, wp_target.emergency_url).to_return(status: 200, body: 'enter your password here') - expect(wp_target.emergency_exists?).to be_truthy - end - - it 'returns false' do - stub_request(:any, wp_target.emergency_url).to_return(status: 500) - expect(wp_target.emergency_exists?).to be_falsey - end - - it 'returns false' do - stub_request(:any, wp_target.emergency_url).to_return(status: 500, body: 'enter your password here') - expect(wp_target.emergency_exists?).to be_falsey - end - end - -end diff --git a/spec/lib/wpscan/wpscan_helper.rb b/spec/lib/wpscan/wpscan_helper.rb deleted file mode 100644 index 079eebd5..00000000 --- a/spec/lib/wpscan/wpscan_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -require WPSCAN_LIB_DIR + '/wpscan_helper' - -SPEC_FIXTURES_WPSCAN_DIR = SPEC_FIXTURES_DIR + '/wpscan' -SPEC_FIXTURES_WPSCAN_WEB_SITE_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/web_site' -SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_target' -SPEC_FIXTURES_WPSCAN_WPSCAN_OPTIONS_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wpscan_options' -SPEC_FIXTURES_WPSCAN_WP_THEME_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_theme' -SPEC_FIXTURES_WPSCAN_WP_PLUGIN_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_plugin' -SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_version' diff --git a/spec/lib/wpscan/wpscan_options_spec.rb b/spec/lib/wpscan/wpscan_options_spec.rb deleted file mode 100644 index 62bc34cf..00000000 --- a/spec/lib/wpscan/wpscan_options_spec.rb +++ /dev/null @@ -1,392 +0,0 @@ -# encoding: UTF-8 - -require File.expand_path(File.join(__dir__, 'wpscan_helper')) - -describe 'WpscanOptions' do - - before :each do - @wpscan_options = WpscanOptions.new - end - - describe '#initialize' do - it 'should set all options to nil' do - WpscanOptions::ACCESSOR_OPTIONS.each do |option| - expect(@wpscan_options.send(option)).to be === nil - end - end - end - - describe '#url=' do - it 'should raise an error if en empty or nil url is supplied' do - expect { @wpscan_options.url = '' }.to raise_error - expect { @wpscan_options.url = nil }.to raise_error - end - - it 'should add the http protocol if not present' do - @wpscan_options.url = 'example.com' - expect(@wpscan_options.url).to be === 'http://example.com' - end - - it "should not add the http protocol if it's already present" do - url = 'http://example.com' - @wpscan_options.url = url - expect(@wpscan_options.url).to be === url - end - - it 'should encode IDN' do - @wpscan_options.url = 'http://пример.испытание/' - expect(@wpscan_options.url).to be === 'http://xn--e1afmkfd.xn--80akhbyknj4f/' - end - end - - describe '#threads=' do - it 'should convert an integer in a string into an integr' do - @wpscan_options.threads = '10' - expect(@wpscan_options.threads).to be_an Integer - expect(@wpscan_options.threads).to be === 10 - end - - it 'should set to correct number of threads' do - @wpscan_options.threads = 15 - expect(@wpscan_options.threads).to be_an Integer - expect(@wpscan_options.threads).to be === 15 - end - end - - describe '#wordlist=' do - it 'should raise an error if the wordlist file does not exist' do - expect { @wpscan_options.wordlist = '/i/do/not/exist.txt' }.to raise_error - end - - it 'should not raise an error' do - wordlist_file = "#{SPEC_FIXTURES_WPSCAN_WPSCAN_OPTIONS_DIR}/wordlist.txt" - - @wpscan_options.wordlist = wordlist_file - expect(@wpscan_options.wordlist).to be === wordlist_file - end - end - - describe '#proxy=' do - it 'should raise an error' do - expect { @wpscan_options.proxy = 'invalidproxy' }.to raise_error - end - - it 'should not raise an error' do - proxy = '127.0.0.1:3038' - @wpscan_options.proxy = proxy - expect(@wpscan_options.proxy).to be === proxy - end - end - - describe '#proxy_auth=' do - it 'should raise an error if the format is not correct' do - expect { @wpscan_options.proxy_auth = 'invalidauth' }.to raise_error - end - - it 'should not raise en error' do - proxy_auth = 'user:pass' - @wpscan_options.proxy_auth = proxy_auth - expect(@wpscan_options.proxy_auth).to be === proxy_auth - end - end - - describe '#enumerate_plugins=' do - it 'should raise an error' do - @wpscan_options.enumerate_only_vulnerable_plugins = true - expect { @wpscan_options.enumerate_plugins = true }.to raise_error( - RuntimeError, 'Please choose only one plugin enumeration option' - ) - end - - it 'should not raise an error' do - @wpscan_options.enumerate_only_vulnerable_plugins = false - @wpscan_options.enumerate_plugins = true - - expect(@wpscan_options.enumerate_plugins).to be_truthy - end - end - - describe '#enumerate_themes=' do - it 'should raise an error' do - @wpscan_options.enumerate_only_vulnerable_themes = true - expect { @wpscan_options.enumerate_themes = true }.to raise_error( - RuntimeError, 'Please choose only one theme enumeration option' - ) - end - - it 'should not raise an error' do - @wpscan_options.enumerate_only_vulnerable_themes = false - @wpscan_options.enumerate_themes = true - - expect(@wpscan_options.enumerate_themes).to be_truthy - end - end - - describe '#enumerate_only_vulnerable_plugins=' do - it 'should raise an error' do - @wpscan_options.enumerate_plugins = true - expect { @wpscan_options.enumerate_only_vulnerable_plugins = true }.to raise_error( - RuntimeError, 'Please choose only one plugin enumeration option' - ) - end - - it 'should not raise an error' do - @wpscan_options.enumerate_plugins = false - @wpscan_options.enumerate_only_vulnerable_plugins = true - - expect(@wpscan_options.enumerate_only_vulnerable_plugins).to be_truthy - end - end - - describe '#enumerate_only_vulnerable_themes=' do - it 'should raise an error' do - @wpscan_options.enumerate_themes = true - expect { @wpscan_options.enumerate_only_vulnerable_themes = true }.to raise_error( - RuntimeError, 'Please choose only one theme enumeration option' - ) - end - - it 'should not raise an error' do - @wpscan_options.enumerate_themes = false - @wpscan_options.enumerate_only_vulnerable_themes = true - - expect(@wpscan_options.enumerate_only_vulnerable_themes).to be_truthy - end - end - - describe '#enumerate_all_themes=' do - it 'should raise an error' do - @wpscan_options.enumerate_themes = true - expect { @wpscan_options.enumerate_all_themes = true }.to raise_error( - RuntimeError, 'Please choose only one theme enumeration option' - ) - end - - it 'should not raise an error' do - @wpscan_options.enumerate_themes = false - @wpscan_options.enumerate_all_themes = true - - expect(@wpscan_options.enumerate_all_themes).to be_truthy - end - end - - describe '#enumerate_all_plugins=' do - it 'should raise an error' do - @wpscan_options.enumerate_plugins = true - expect { @wpscan_options.enumerate_all_plugins = true }.to raise_error( - RuntimeError, 'Please choose only one plugin enumeration option' - ) - end - - it 'should not raise an error' do - @wpscan_options.enumerate_plugins = false - @wpscan_options.enumerate_all_plugins = true - - expect(@wpscan_options.enumerate_all_plugins).to be_truthy - end - end - - describe '#has_options?' do - it 'should return false' do - expect(@wpscan_options.has_options?).to be_falsey - end - - it 'should return true' do - @wpscan_options.verbose = false - expect(@wpscan_options.has_options?).to be_truthy - end - end - - describe '#to_h' do - it 'should return an empty hash' do - expect(@wpscan_options.to_h).to be_a Hash - expect(@wpscan_options.to_h).to be_empty - end - - it 'should return a hash with :verbose = true' do - expected = {verbose: true} - @wpscan_options.verbose = true - - expect(@wpscan_options.to_h).to be === expected - end - end - - describe '#clean_option' do - after :each do - expect(WpscanOptions.clean_option(@option)).to be === @expected - end - - it "should return 'url'" do - @option = '--url' - @expected = 'url' - end - - it "should return 'u'" do - @option = '-u' - @expected = 'u' - end - - it "should return 'follow_redirection'" do - @option = '--follow-redirection' - @expected = 'follow_redirection' - end - end - - describe '#option_to_instance_variable_setter' do - after :each do - expect(WpscanOptions.option_to_instance_variable_setter(@argument)).to be === @expected - end - - it 'should return :url=' do - @argument = '--url' - @expected = :url= - end - - it 'should return :verbose=' do - @argument = '--verbose' - @expected = :verbose= - end - - it 'should return :proxy= for --proxy' do - @argument = '--proxy' - @expected = :proxy= - end - - it 'should return nil for --enumerate' do - @argument = '--enumerate' - @expected = nil - end - - it 'should return :proxy_auth= for --proxy_auth' do - @argument = '--proxy_auth' - @expected = :proxy_auth= - end - end - - describe '#is_long_option?' do - it 'should return true' do - expect(WpscanOptions.is_long_option?('--url')).to be_truthy - end - - it 'should return false' do - expect(WpscanOptions.is_long_option?('hello')).to be_falsey - expect(WpscanOptions.is_long_option?('--enumerate')).to be_falsey - end - end - - describe '#enumerate_options_from_string' do - after :each do - if @argument - wpscan_options = WpscanOptions.new - wpscan_options.enumerate_options_from_string(@argument) - expect(wpscan_options.to_h).to be === @expected_hash - end - end - - it 'should raise an error if p and p! are ' do - expect { @wpscan_options.enumerate_options_from_string('p,vp') }.to raise_error - end - - it 'should set enumerate_plugins to true' do - @argument = 'p' - @expected_hash = {enumerate_plugins: true} - end - - it 'should set enumerate_only_vulnerable_plugins to tue' do - @argument = 'vp' - @expected_hash = {enumerate_only_vulnerable_plugins: true} - end - - it 'should set enumerate_timthumbs to true' do - @argument = 'tt' - @expected_hash = {enumerate_timthumbs: true} - end - - it 'should set enumerate_usernames to true' do - @argument = 'u' - @expected_hash = {enumerate_usernames: true} - end - - it 'should set enumerate_usernames to true and enumerate_usernames_range to (1..20)' do - @argument = 'u[1-20]' - @expected_hash = {enumerate_usernames: true, enumerate_usernames_range: (1..20)} - end - - # Let's try some multiple choices - it 'should set enumerate_timthumbs to true, enumerate_usernames to true, enumerate_usernames_range to (1..2)' do - @argument = 'u[1-2],tt' - @expected_hash = { - enumerate_usernames: true, enumerate_usernames_range: (1..2), - enumerate_timthumbs: true - } - end - end - - describe '#set_option_from_cli' do - it 'should raise an error with unknow option' do - expect { @wpscan_options.set_option_from_cli('hello', '') }.to raise_error - end - - it 'should set @url to example.com' do - @wpscan_options.set_option_from_cli('--url', 'example.com') - expect(@wpscan_options.url).to be === 'http://example.com' - end - - it 'should set @enumerate_plugins to true' do - @wpscan_options.set_option_from_cli('--enumerate', 'p') - expect(@wpscan_options.enumerate_plugins).to be_truthy - expect(@wpscan_options.enumerate_only_vulnerable_plugins).to be_nil - end - - it 'should set @enumerate_only_vulnerable_plugins, @enumerate_timthumbs and @enumerate_usernames to true if no argument is given' do - @wpscan_options.set_option_from_cli('--enumerate', '') - expect(@wpscan_options.enumerate_only_vulnerable_plugins).to be_truthy - expect(@wpscan_options.enumerate_timthumbs).to be_truthy - expect(@wpscan_options.enumerate_usernames).to be_truthy - end - end - - describe '#load_from_arguments' do - after :each do - set_argv(@argv) - wpscan_options = WpscanOptions.load_from_arguments - expect(wpscan_options.to_h).to be === @expected_hash - end - - it 'should return {}' do - @argv = '' - @expected_hash = {} - end - - it "should return {:url => 'example.com'}" do - @argv = '--url example.com' - @expected_hash = { url: 'http://example.com' } - end - - it "should return {:url => 'example.com'}" do - @argv = '-u example.com' - @expected_hash = { url: 'http://example.com' } - end - - it "should return {:username => 'admin'}" do - @argv = '--username admin' - @expected_hash = { username: 'admin' } - end - - it "should return {:username => 'Youhou'}" do - @argv = '-U Youhou' - @expected_hash = { username: 'Youhou' } - end - - it "should return {:url => 'example.com', :threads => 5, :force => ''}" do - @argv = '-u example.com --force -t 5' - @expected_hash = { url: 'http://example.com', threads: 5, force: '' } - end - - it "should return {:url => 'example.com', :enumerate_plugins => true, :enumerate_timthumbs => true}" do - @argv = '-u example.com -e p,tt' - @expected_hash = { url: 'http://example.com', enumerate_plugins: true, enumerate_timthumbs: true } - end - end - -end diff --git a/spec/samples/common/collections/wp_items/detectable/passive_detection.html b/spec/samples/common/collections/wp_items/detectable/passive_detection.html deleted file mode 100644 index 06139300..00000000 --- a/spec/samples/common/collections/wp_items/detectable/passive_detection.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - example.com - - - - - - - - - - - - - - - - - - - - - - - - - - - http://example.com/wp-content/items/this-should-not-match/sub.css - href="http://example.com/wp-content/items/this-should-not-match/sub.css" - /wp-content/items/this-should-not-match/sub.css - //wp-content/items/this-should-not-match/sub.css - src='/wp-content/items/this-should-not-match/sub.css' - - - - diff --git a/spec/samples/common/collections/wp_items/detectable/targets.txt b/spec/samples/common/collections/wp_items/detectable/targets.txt deleted file mode 100644 index 98074375..00000000 --- a/spec/samples/common/collections/wp_items/detectable/targets.txt +++ /dev/null @@ -1,3 +0,0 @@ -item1 -item-2 -mr-smith diff --git a/spec/samples/common/collections/wp_items/detectable/vulns.json b/spec/samples/common/collections/wp_items/detectable/vulns.json deleted file mode 100644 index 80ee2ba6..00000000 --- a/spec/samples/common/collections/wp_items/detectable/vulns.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "mr-smith": { - "vulnerabilities":[ - { - "id":2989, - "title":"Administrator-exploitable blind SQLi in WordPress 1.0 - 3.8.1", - "references": { - "url": "https://security.dxw.com/advisories/sqli-in-wordpress-3-6-1/,http://www.example.com" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:43:41.000Z" - }, - { - "id":2990, - "title":"Potential Authentication Cookie Forgery", - "references": { - "url": "https://labs.mwrinfosecurity.com/blog/2014/04/11/wordpress-auth-cookie-forgery/,https://github.com/WordPress/WordPress/commit/78a915e0e5927cf413aa6c2cef2fca3dc587f8be", - "osvdb":"105620", - "cve":"2014-0166" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z", - "fixed_in":"3.8.2" - }, - { - "id":2991, - "title":"Privilege escalation: contributors publishing posts", - "references": { - "url": "https://github.com/wpscanteam/wpscan/wiki/CVE-2014-0165", - "osvdb":"105630", - "cve":"2014-0165" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z", - "fixed_in":"3.8.2" - }, - { - "id":2992, - "title":"Plupload Unspecified XSS", - "references": { - "osvdb":"105622", - "secunia":"57769" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z", - "fixed_in":"3.8.2" - } - ] - }, - "neo": { - "vulnerabilities":[ - { - "id":2993, - "title":"wp-admin/options-writing.php Cleartext Admin Credentials Disclosure", - "references": { - "url": "http://seclists.org/fulldisclosure/2013/Dec/135", - "osvdb":"101101" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - } - ] - } -} diff --git a/spec/samples/common/collections/wp_plugins/detectable/passive_detection.html b/spec/samples/common/collections/wp_plugins/detectable/passive_detection.html deleted file mode 100644 index 2ef3f5cb..00000000 --- a/spec/samples/common/collections/wp_plugins/detectable/passive_detection.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - Example.com - - - - - - - - - - - - - - -
-
-

- Blablabla the following plugin should not match : /wp-content/plugins/this-plugin-should-not-match/sub.css -

-
-
- - - - - - - - diff --git a/spec/samples/common/collections/wp_plugins/detectable/targets.txt b/spec/samples/common/collections/wp_plugins/detectable/targets.txt deleted file mode 100644 index d87b6b26..00000000 --- a/spec/samples/common/collections/wp_plugins/detectable/targets.txt +++ /dev/null @@ -1,3 +0,0 @@ -plugin1 -plugin-2 -mr-smith diff --git a/spec/samples/common/collections/wp_plugins/detectable/vulns.json b/spec/samples/common/collections/wp_plugins/detectable/vulns.json deleted file mode 100644 index 6b0e28cc..00000000 --- a/spec/samples/common/collections/wp_plugins/detectable/vulns.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "mr-smith": { - "vulnerabilities":[ - { - "id":2989, - "title":"Administrator-exploitable blind SQLi in WordPress 1.0 - 3.8.1", - "references": { - "url": "https://security.dxw.com/advisories/sqli-in-wordpress-3-6-1/,http://www.example.com" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:43:41.000Z" - }, - { - "id":2990, - "title":"Potential Authentication Cookie Forgery", - "references": { - "url": "https://labs.mwrinfosecurity.com/blog/2014/04/11/wordpress-auth-cookie-forgery/,https://github.com/WordPress/WordPress/commit/78a915e0e5927cf413aa6c2cef2fca3dc587f8be" - }, - "osvdb":"105620", - "cve":"2014-0166", - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z", - "fixed_in":"3.8.2" - }, - { - "id":2991, - "title":"Privilege escalation: contributors publishing posts", - "references": { - "url": "https://github.com/wpscanteam/wpscan/wiki/CVE-2014-0165", - "osvdb":"105630", - "cve":"2014-0165" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z", - "fixed_in":"3.8.2" - }, - { - "id":2992, - "title":"Plupload Unspecified XSS", - "references": { - "osvdb":"105622", - "secunia":"57769" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z", - "fixed_in":"3.8.2" - } - ] - }, - "neo": { - "vulnerabilities":[ - { - "id":2993, - "title":"wp-admin/options-writing.php Cleartext Admin Credentials Disclosure", - "references": { - "url": "http://seclists.org/fulldisclosure/2013/Dec/135", - "osvdb":"101101" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - } - ] - } -} diff --git a/spec/samples/common/collections/wp_themes/detectable/passive_detection.html b/spec/samples/common/collections/wp_themes/detectable/passive_detection.html deleted file mode 100644 index 9b741167..00000000 --- a/spec/samples/common/collections/wp_themes/detectable/passive_detection.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - Example.com - - - - - - - - - - - -
-
-

- Blablabla -

-
-
- - - diff --git a/spec/samples/common/collections/wp_themes/detectable/targets.txt b/spec/samples/common/collections/wp_themes/detectable/targets.txt deleted file mode 100644 index 5fc51166..00000000 --- a/spec/samples/common/collections/wp_themes/detectable/targets.txt +++ /dev/null @@ -1,3 +0,0 @@ -3colours -42k -a-ri diff --git a/spec/samples/common/collections/wp_themes/detectable/vulns.json b/spec/samples/common/collections/wp_themes/detectable/vulns.json deleted file mode 100644 index 086ae752..00000000 --- a/spec/samples/common/collections/wp_themes/detectable/vulns.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "shopperpress": { - "vulnerabilities":[ - { - "id":2989, - "title":"Administrator-exploitable blind SQLi in WordPress 1.0 - 3.8.1", - "references": { - "url": "https://security.dxw.com/advisories/sqli-in-wordpress-3-6-1/,http://www.example.com" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:43:41.000Z" - }, - { - "id":2990, - "title":"Potential Authentication Cookie Forgery", - "references": { - "url": "https://labs.mwrinfosecurity.com/blog/2014/04/11/wordpress-auth-cookie-forgery/,https://github.com/WordPress/WordPress/commit/78a915e0e5927cf413aa6c2cef2fca3dc587f8be", - "osvdb":"105620", - "cve":"2014-0166" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z", - "fixed_in":"3.8.2" - }, - { - "id":2991, - "title":"Privilege escalation: contributors publishing posts", - "references": { - "url": "https://github.com/wpscanteam/wpscan/wiki/CVE-2014-0165", - "osvdb":"105630", - "cve":"2014-0165" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z", - "fixed_in":"3.8.2" - }, - { - "id":2992, - "title":"Plupload Unspecified XSS", - "references": { - "osvdb":"105622", - "secunia":"57769" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z", - "fixed_in":"3.8.2" - } - ] - }, - "webfolio": { - "vulnerabilities":[ - { - "id":2993, - "title":"wp-admin/options-writing.php Cleartext Admin Credentials Disclosure", - "references": { - "url": "http://seclists.org/fulldisclosure/2013/Dec/135", - "osvdb":"101101" - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - } - ] - } -} - diff --git a/spec/samples/common/collections/wp_timthumbs/detectable/targets.txt b/spec/samples/common/collections/wp_timthumbs/detectable/targets.txt deleted file mode 100644 index 33f019f2..00000000 --- a/spec/samples/common/collections/wp_timthumbs/detectable/targets.txt +++ /dev/null @@ -1,4 +0,0 @@ -timthumb.php -$wp-content$/timthumb.php -$wp-plugins$/a-gallery/timthumb.php -$wp-content$/themes/theme-name/timthumb.php diff --git a/spec/samples/common/models/vulnerability/json_item.json b/spec/samples/common/models/vulnerability/json_item.json deleted file mode 100644 index 778d4ba5..00000000 --- a/spec/samples/common/models/vulnerability/json_item.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "id": "3911", - "title": "Vuln Title", - "references":{ - "url": "Ref 1,Ref 2", - "secunia": "secunia", - "osvdb": "osvdb", - "cve": "2011-001", - "metasploit": "exploit/ex1", - "exploitdb": "exploitdb" - }, - "created_at": "2014-07-28T12:10:45.000Z", - "updated_at": "2014-07-28T12:10:45.000Z", - "type": "CSRF", - "fixed_in": "1.0" -} diff --git a/spec/samples/common/models/wp_item/error_log b/spec/samples/common/models/wp_item/error_log deleted file mode 100644 index 5836f0c1..00000000 --- a/spec/samples/common/models/wp_item/error_log +++ /dev/null @@ -1,25 +0,0 @@ -[13-Jan-2009 01:53:25] PHP Fatal error: Class 'Log' not found in /home/****/public_html/svatba/wp-content/plugins/fbconnect/Log/null.php on line 19 -[13-Jan-2009 01:55:58] PHP Fatal error: Class 'Log' not found in /home/****/public_html/svatba/wp-content/plugins/fbconnect/Log/file.php on line 20 -[13-Jan-2009 02:13:34] PHP Fatal error: Class 'Log' not found in /home/****/public_html/svatba/wp-content/plugins/fbconnect/Log/error_log.php on line 19 -[15-Feb-2009 10:47:54] PHP Fatal error: Class 'Log' not found in /home/****/public_html/svatba/wp-content/plugins/fbconnect/Log/error_log.php on line 19 -[15-Feb-2009 11:36:15] PHP Fatal error: Class 'Log' not found in /home/****/public_html/svatba/wp-content/plugins/fbconnect/Log/null.php on line 19 -[15-Feb-2009 16:45:37] PHP Fatal error: Class 'Log' not found in /home/****/public_html/svatba/wp-content/plugins/fbconnect/Log/file.php on line 20 -[04-Mar-2009 18:54:31] PHP Fatal error: Class 'Log' not found in /home/****/public_html/svatba/wp-content/plugins/fbconnect/Log/file.php on line 20 -[21-Mar-2009 20:32:21] PHP Fatal error: Class 'Log' not found in /home/****/public_html/svatba/wp-content/plugins/fbconnect/Log/null.php on line 19 -[29-Mar-2009 16:25:40] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/null.php on line 19 -[06-Apr-2009 01:17:56] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/file.php on line 20 -[03-May-2009 00:07:57] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/null.php on line 19 -[10-May-2009 05:57:57] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/file.php on line 20 -[21-May-2009 01:23:52] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/error_log.php on line 19 -[02-Jun-2009 23:10:20] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/null.php on line 19 -[17-Jun-2009 13:49:05] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/error_log.php on line 19 -[17-Jun-2009 14:57:33] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/error_log.php on line 19 -[23-Jun-2009 01:55:21] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/file.php on line 20 -[06-Aug-2009 09:27:53] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/null.php on line 19 -[31-Aug-2009 22:13:54] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/file.php on line 20 -[03-Sep-2009 15:20:03] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/error_log.php on line 19 -[13-Sep-2009 07:49:45] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/null.php on line 19 -[22-Sep-2009 19:46:47] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/file.php on line 20 -[02-Feb-2010 15:52:56] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/file.php on line 20 -[02-Feb-2010 16:05:19] PHP Fatal error: Class 'Log' not found in /home3/****/public_html/svatba/wp-content/plugins/fbconnect/Log/null.php on line 19 - diff --git a/spec/samples/common/models/wp_item/existable/cache_generation.html b/spec/samples/common/models/wp_item/existable/cache_generation.html deleted file mode 100644 index b02ff386..00000000 --- a/spec/samples/common/models/wp_item/existable/cache_generation.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - -Lamp Testing - - - - - -
-
- - - diff --git a/spec/samples/common/models/wp_item/versionable/a-lead-capture-contact-form-and-tab-button-by-awebvoicecom.txt b/spec/samples/common/models/wp_item/versionable/a-lead-capture-contact-form-and-tab-button-by-awebvoicecom.txt deleted file mode 100644 index 25651e8b..00000000 --- a/spec/samples/common/models/wp_item/versionable/a-lead-capture-contact-form-and-tab-button-by-awebvoicecom.txt +++ /dev/null @@ -1,103 +0,0 @@ -=== A Capture Contact Form (and tab) by AWebVoice.com === -Contributors: AWebVoice -Donate link: -Tags: contact form, web form, capture contact form, response forms, captcha form, get response, contact me, contact form 7 -Requires at least: 2.0.2 -Tested up to: 3.1.1 -Stable tag: trunk - -Get a contact form and a contact button. Capture your visitors and turn them into customers! - -== Description == - -A fully customizable contact form on your WordPress blog. And a contact tab to increase customer interaction. Join our fast growing users base who have chosen AWebVoice as their contact form of choice! - -= Get your FREE Contact Form plugin for Wordpress = - -Our Contact Form plugin is full of features that no other wordpress contact form can offer. See for yourself, below are a few of the features we offer: - -* Add a customized contact form to your Wordpress blog which includes a message, contact's email, name, phone number and more! -* Create and customize your contact form settings right from within your Wordpress Admin Panel -* Include your logo, business contact info, even social links right on your contact form -* Notifications: Get a contacts message notifications to your inbox! -* Setup multiple autoresponder for your contact form so your visitors get an instant message from you -* Take your autoresponders to the next level, and ask your contact to join your email list. -* Setup a custom success message or URL for your contact form -* Each form has built in ROI tracking -* Increases conversion: Include a custom “Contact” tab to the side of your wordpress blog that pops up your contact form. -* ...these features will always be free, but go to the next level and get many more features for your contact form! - -= More than a Contact Form = - -Behind the AWebVoice wordpress plugin contact form is a suite of online tools to effectively manage all of your leads, contacts, and marketing ROI needs. As leads come in from your contact form, those contacts are automatically added to your online contacts database. From there, access information about each contact, send emails to each contact, and fully track, organize, and manage your communications. AWebVoice.com is designed to scale from single person offices to Fortune 500 companies -- and it is created on the very largest online database has to offer. - - -= And it is easy to get start = - -AWebVoice.com’s contact form is FREE and is the easiest wordpress contact form to use. We think you will agree, give it a try sign up now: -www.awebvoice.com. - -== Installation == - -= Option 1: Install the plugin via your Wordpress admin panel = -1. Login to your Wordpress system which should take you to the Dashboard of your Wordpress account. -1. Click the "Plugins" menu on the left menu bar. The choose "Add New". -1. Search for "AWebVoice", "Contact " or "contact form". -1. Click Install Now, the "Contact Form" by AWebVoice.com. -1. After installation has finished, you need to activate the plugin. -1. You should see the AWebVoice plugin listed in the available plugins. Click the "Activate" link. -1. Next, click the "Settings" menu on the left menu bar and choose "AWebVoice Form" -1. A form will be presented. Enter the e-mail address to receive contact form messages, and click "Create Account". -1. Your AWebVoice tab-button and contact form have been installed and are working on your blog. - -= Option 2: Manual plugin installation = -1. Click on the red "Download Version x.x" button on the right side of this page. -1. After the download has finished, extract the files. -1. Upload the "awebvoivce" folder to your server in "/wp-content/plugins" directory -1. Login to you Wordpress system which should take you to the admin panel or Dashboard. Click on "Plugins" menu. -1. You should see the AWebVoice plugin listed in the available plugins. Click the "Activate" link. -1. Then click on the "Settings" menu in the left side menu bar. Choose "AWebVoice Form" -1. A form will be presented. Enter the e-mail address to receive contact form messages, and click "Create Account". -1. Your AWebVoice tab-button and contact form have been installed and are working on your blog. - -== Frequently Asked Questions == - -= What is Contact Form by AWebVoice.com? = -Unlike other contact form providers like contact form 7, you will never have to touch a line of code to create, edit, or modify your contact form. Just install the Awebvoice.com contact form plugin, choose the email address you want your form submissions to go to, and that is it. Your new contacts are delivered to the specified email address AND stored in an online database under your name. Your contacts are yours and not shared with others. How you use your new contacts is up to you. - -= Can I customize my contact form? = -Yes. Editing a form is quick and easy. In your WordPress administration page, click on Settings. Click on the AWebVoice plugin and click the modify button to edit your contact form. (You may have to login first to AWebVoice.com) With the AWebVoice contact form editor, you can create a beautiful and customized contact forms, including your logo, your address and phone, and more. - -= What is the AWebVoice tab-button? = -The tab-button is a button that sits on the side of your blog and maintains position even as your visitors scroll. Your potential new contacts or existing contacts are only one click away from sending you a message! When the button is clicked, your contact form pops right up in a nice modal window, darkening the rest of the screen and focusing the user on completing your contact form. This AWebVoice tab-button and contact form combination has been proven improve conversions on a website by over 45%. - -= What other unique features do you offer? = -Many more features. AWebVoice is a full featured email, newsletter, coupon marketing system. The tab-button and contact form will always be free. But if you need more, such as self-managed email lists, we have it. We also have ROI reports so you can track your contact form and blog success rate. The AWebVoice Email/Newsletter management system is a subscription based system. We want to help you get started, and once the task of managing your contact list get too large, we are there to support your efforts. AWebVoice is the most effective marketing tool a small or large business can have. - -Get your free AWebVoice contact form today and start watching your leads grow! - -== Screenshots == - -1. Contact Form Admin Panel -2. A Contact Form -3. Contact Tab-Button on the Blog (click opens contact form) - -== Change Log == - -= Coming Soon = -* Contact Form: More custom from fields for your contact form -* Contact Form: More languages for button and contact form - -= 3.1 = -* Initial WordPress Release. -* Analytics included in Contact Form -* Custom form fields for your contact form -* Form title is editable - -== Upgrade Notice == - -= 1.0 = -Upgrade notices when available will be described in this section. - -= Languages = -* English: Available contact form and button diff --git a/spec/samples/common/models/wp_item/versionable/aa-health-calculator.txt b/spec/samples/common/models/wp_item/versionable/aa-health-calculator.txt deleted file mode 100644 index 8dd6d60a..00000000 --- a/spec/samples/common/models/wp_item/versionable/aa-health-calculator.txt +++ /dev/null @@ -1,13 +0,0 @@ -=== Plugin Name === - AA health calculator - - - -Tags:aa ,health,calculator -Requires at least:4.0 -Tested up to:4.0 -Stable tag:aahealthcalculator -License: GPL -Contributors :A and A -==Description== -use [health] shortcode diff --git a/spec/samples/common/models/wp_item/versionable/advanced-most-recent-posts-mod.txt b/spec/samples/common/models/wp_item/versionable/advanced-most-recent-posts-mod.txt deleted file mode 100644 index 568a9294..00000000 --- a/spec/samples/common/models/wp_item/versionable/advanced-most-recent-posts-mod.txt +++ /dev/null @@ -1,215 +0,0 @@ -=== Advanced Most Recent Posts Mod === -Contributors: yakuphan, trepmal -Tags: Advanced, recent, recent posts, most recent, category posts, thumbnail -Donate link: http://kaileylampert.com/donate/ -Requires at least: 2.8 -Tested up to: 3.2.1 -Stable tag: trunk - -Based off the Advanced Most Recent Posts plugin by Yakup GÖVLER. Display most recent posts from selected categories or current category or all categories with thumbnail images (optional). - -== Description == -Advanced Most Recent Posts Widget displays your recent posts with thumbnail images (optional). It gets posts from selected categories or current category or all categories. When your visitors are at home, it gets posts from all posts or selected category. If you set 'Get posts from current category', when visitors see single post, widget lists posts in the same category of single post or when visitors click a category link, it gets posts from current category. - -Check out a brand new plugin inspired by this one: [Mini Loops](http://wordpress.org/extend/plugins/mini-loops/) - -I'm bad at support (not intentionally). If you have questions: check the forums, then check [my blog post's comment thread](http://trepmal.com/plugins/advanced-most-recent-posts-mod/#comments). If that doesn't work, post to the forums (there are awesome volunteers out there!) and get my attention by pinging me on twitter [@trepmal](http://twitter.com/trepmal). - -== Installation == - -= Installation = -1. Make sure you are running WordPress version 2.8 or better. It won't work with older versions. -2. Download the zip file and extract the contents. -3. Upload the 'advanced-most-recent-posts' folder (wp-content/plugins/). -4. Activate the plugin through the 'plugins' page in WP. -5. See 'Appearance'->'Widgets' to place it on your sidebar. Set the settings. - -== Frequently Asked Questions == - -= How can I set it to get posts from current category? = -Select checkbox on widget's settings called 'Get posts from current category'. - -= I want to display only the posts in two categories. = -You have to write their category's ids -separated with a comma- to 'Categories' textbox. - -= I don't use Widgets. How can use this widget? = - -template tag: `yg_recentposts( $args )` -shortcode: `[amrp]` with args -Original author's [website](http://www.yakupgovler.com/?p=1033). - -= .... Image alignment .... = - -If you need serious customization, please go learn CSS. I will not provide extensive CSS support. (Sorry - there are just far too many variations, and I do all this in my spare time) - -The most frequest request I get has to do with aligning the image to the right or left. To get started with customization, create a file called amrp-styles.php (really, any name will do) and upload it to `wp-content/mu-plugins` (you may need to create this directory). - -In that file, paste the following -` - - 'Widgets' -2. (original version) Widget's screenshot in 'Appearance'->'Widgets' - -== Options == - -Widget's options allow you to change your recent posts list displaying. - -= Title: = -Your recent posts widget's title on your sidebar. - -= Title Link: = -The page the title should link to. - -= Hide Post Title: = -Check to hide post title in output. useful for thumbnail-only displays - -= Separator: = -The character to use to separate the title from the excerpt. - -= After Excerpt: = -What should appear after the excerpt - -= After Excerpt Link: = -should the 'after excerpt' text link to the post? useful if 'after excerpt' read like "read more..." - -= Show: = -The post type to be displayed. - -= Number of posts to show: = -How many posts to display - -= Excerpt length (letters) = -You know that - -= Thumbnail Custom Field Name = -If you want to display the thumbnail of your posts via a custom field, write its name. - -= Height - Width = -Images size. - -= Get first image of post = -If you don't want to use custom field, plugin will get first image from your post content. - -= Get first attached image of post = -Plugin gets first attached image of post. - -= Default image = -If post has no image, plugin display this image. Ex: http://www.yakupgovler.com/default-image.png - - -Notice: If you use three options, plugin uses custom field image firstly. If the post has no custom field, it gets first image from content. At last it gets first attached image. I suggest not to use "Get first image of post" for performance. It queries much more. - -= Show Author = -If checked, shows author next to title - -= Show Post Timestamp = -If checked, shows post timestamp - -= Time format = -The format to be used when displaying the timestamp - -= Put time = -A placement option for the post timestamp - -= Categories = -Plugin gets posts in these categories. (Category IDs, separated by commas.) - -= Get posts from current category: = -Posts will be get from current category (single post's category or current category). - - -== Upgrade Notice == - -= 1.6.5 = -bugfix: 'after excerpt' now appears as it should even if the link option is unchecked -Have you tried [Mini Loops](http://wordpress.org/extend/plugins/mini-loops/)? - -= 1.6.4 = -moved image outside of title so it won't disappear if 'hide title' is checked -undefined variable bug fix - -= 1.6.3 = -fixed after-excerpt-link bug - -= 1.6 = -Future updates will assume you have at least this release. - -== Changelog == - -= 1.6.5.2 = -* it title is empty, show nothing not default - -= 1.6.5.1 = -* updated POT file - -= 1.6.5 = -* bugfix: 'after excerpt' now appears as it should even if the link option is unchecked - -= 1.6.4 = -* moved image outside of title so it won't disappear if 'hide title' is checked -* undefined variable bug fix - -= 1.6.3 = -* fixed after-excerpt-link bug - -= 1.6.2 = -* shortcode fixes for 'limit' (really should be 'shownum' - now both work) and height/width - -= 1.6.1 = -* author fix - -= 1.6 = -* remove 20 post limit -* option to display posts in reverse order -* excerpt by *word* count option -* post-offset option - -= 1.5 = -* *dev release* -* option to hide post title -* option to specify the '...' after excerpt - -= 1.4.1 = -* fixed double echo issue - -= 1.4 = -* added support for shortcodes, show author option and post-type choice - -= 1.3 = -* fixed timestamp bug, added timestamp placement option - -= 1.2 = -* added support for setting a title link, choosing a title/content separator, and displaying post timestamp - -= 1.1 = -* (original plugin) Fixed a bug. If you don't set image dimensions, it displays thumbnail wrong. - -= Version 1.0 = -* Initial release version. diff --git a/spec/samples/common/models/wp_item/versionable/all-in-one-facebook.txt b/spec/samples/common/models/wp_item/versionable/all-in-one-facebook.txt deleted file mode 100644 index 9ca2df81..00000000 --- a/spec/samples/common/models/wp_item/versionable/all-in-one-facebook.txt +++ /dev/null @@ -1,39 +0,0 @@ -=== All In One Facebook === -Contributors: rahadgp -Donate link: -Tags: facebook,Social Networking,Wordpress Facebook widget, twiter widget -Requires at least: 3.3 -Tested up to: 3.8 -Stable tag: all in one facebook -License: GPLv2 or later -License URI: http://www.gnu.org/licenses/gpl-2.0.html - -With this widget and plugin combination , you can display a customizable JQUERY accordion which gathers Facebook social plugins together with option which to be display or which you don't want to display in your side bar or widget area, and by the plugin you can set short code for each and every thing what you want to put in your post on your website . - -== Description == -With this widget , you can display a customizable frame which gathers Facebook social plugins together with option which to be display or which you don't want to display in your side bar or widget area, and by the plugin you can set short code for each and every thing what you want to put in your post on your website . As a whole new feature like and share feature has been implemented with like box, recommends and twitter feed integration. - -== Installation == - -1. Upload `plugin-name.php` to the `/wp-content/plugins/` directory -1. Activate the plugin through the 'Plugins' menu in WordPress - -== Frequently asked questions == - - - -== Screenshots == -1. Setting Page for the facebook plugin -2. Setting page -3. Setting Page - - -== Changelog == - - - -== Upgrade notice == - - - -== Arbitrary section 1 == diff --git a/spec/samples/common/models/wp_item/versionable/backup-scheduler.txt b/spec/samples/common/models/wp_item/versionable/backup-scheduler.txt deleted file mode 100644 index 088d4948..00000000 --- a/spec/samples/common/models/wp_item/versionable/backup-scheduler.txt +++ /dev/null @@ -1,224 +0,0 @@ -=== Backup Scheduler === - -Author: SedLex -Contributors: SedLex -Author URI: http://www.sedlex.fr/ -Plugin URI: http://wordpress.org/plugins/backup-scheduler/ -Tags: backup, schedule, plugin, save, database, zip -Requires at least: 3.0 -Tested up to: 4.2 -Stable tag: trunk -License: GPLv3 - -With this plugin, you may plan the backup of your entire website (folders, files and/or database). - -== Description == - -With this plugin, you may plan the backup of your entire website (folders, files and/or database). - -You can choose: - -* which folders you want to save; -* the frequency of the backup process; -* whether your database should be saved; -* whether the backup is stored on the local website, sent by email or stored on a distant FTP (support of multipart zip files) - -This plugin is under GPL licence - -= Multisite - Wordpress MU = - -This plugin is compatible with Multisite installation. - -Each blog administrator may save their own data. - -The super-admin may save either its data or the whole website. By saving the whole site, the admin may create different SQL files for the subsite in order to ease the restoration of a single sub-site. - -= Localization = - -* German (Switzerland) translation provided by PeterDbbert, BernhardKnab, scream -* German (Germany) translation provided by agent-test, agent, bartdev2000, Ditoran, GLassnig -* English (United States), default language -* Spanish (Spain) translation provided by Javier, AVfoto, charliechin, IgnacioCalvo, JordiVives, FelipeJAG -* Farsi (Iran) translation provided by sehrama.ir -* Finnish (Finland) translation provided by AnttiSilvola -* French (France) translation provided by SedLex, wkpixearts, Matthieu, mutmut, anonymous, noaneo, TonyLand -* Indonesian (Indonesia) translation provided by ceceparif -* Indonesian (Indonesia) translation provided by Faleddo -* Italian (Italy) translation provided by PuntoCon -* Dutch (Netherlands) translation provided by Matrix, WybAnema, Jay -* Polish (Poland) translation provided by Opti, Lukasz, pablo, Misiek, MarekMackiewicz, Darbo -* Portuguese (Brazil) translation provided by RainilsonRodriguis, GuiBeloto -* Portuguese (Portugal) translation provided by FranciscoRocha -* Russian (Russia) translation provided by GerinG, Slawka, Berdych -* Swedish (Sweden) translation provided by -* Thai (Thailand) translation provided by tontan -* Turkish (Turkey) translation provided by UfukArt -* Chinese (People's Republic of China) translation provided by YiscaJoe, jeffli - -= Features of the framework = - -This plugin uses the SL framework. This framework eases the creation of new plugins by providing tools and frames (see dev-toolbox plugin for more info). - -You may easily translate the text of the plugin and submit it to the developer, send a feedback, or choose the location of the plugin in the admin panel. - -Have fun ! - -== Installation == - -1. Upload this folder backup-scheduler to your plugin directory (for instance '/wp-content/plugins/') -2. Activate the plugin through the 'Plugins' menu in WordPress -3. Navigate to the 'SL plugins' box -4. All plugins developed with the SL core will be listed in this box -5. Enjoy ! - -== Screenshots == - -1. A list of all backup files -2. The configuration page of the plugin - -== Changelog == - -= 1.5.9 = -* NEW: Add icons - -= 1.5.8 = -* NEW: Exclusion folder is now possible with regexp - -= 1.5.7 = -* NEW: Exclusion folder enabled -* NEW: Detailed HOW TO - -= 1.5.6 = -* BUG : Problem of activation with version of PHP below 5.2 - -= 1.5.5 = -* NEW : Take into account blogs.dir and site - -= 1.5.4 = -* NEW : By saving the whole site, the admin may create different SQL files for the subsite in order to ease the restoration of a single sub-site. - -= 1.5.3 = -* BUG: On some configuration, <? is not supported - -= 1.5.2 = -* NEW: You may now create subfolder in the FTP directory -* NEW: improve the look of the configuration page - -= 1.5.1 = -* BUG: improve the summary mail -* NEW: indicate if the FTP transfer has been successful in the backend -* NEW: few enhancement in the framework - -= 1.5.0 = -* Major improvement of the database backup -* the summary mail now displays the issues with the ftp transfer - -= 1.4.0 -> 1.4.4 = -* Change the URL of the plugin on Wordpress -* Some modification -* Some issues in the framework -* Cleaning the framework to avoid unnecessarly code -* A bug that do not delete the lock file when reseting the backup process -* Enhance the performance of the backup process and ensure error protection -* Improve the mail summary -* Enhance the feedback tab -* Improve the core - -= 1.3.0 -> 1.3.7 = -* FTP bug with some webhosting service -* FTP port may be changed -* The error message is muck more explicit -* Add a drop if exist in SQL table -* Bug with multisite and remove a false positive error with wordfence -* There was a bug in the regexp when the ftp were directed to the root folder without any slash at the end. -* Add deletion features when uninstalling the plugin -* Multisite compatible -* Improve the zip compatibilities -* Add log features - -= 1.2.0 -> 1.2.8 = -* Some spanned zip files were corrupted due to a bug in the index -* Remove short_open_tag -* Tuning to be able to work with very huge database -* Bug with NULL values in the database -* FTP support -* Full site backup is now possible -* Bug correction when SQL has NULL value -* Add a link to delete manually the backup (feature requested by Mirza) -* You can also force a new update without sending the emails -* Improve error management and memory leakage - -= 1.1.0 -> 1.1.5 = -* Bug in the sql file : date and time managements were incorrect -* Add a time option for choosing the best moment to perform an automatic backup -* Display bug correction -* Add instructions to restore the backup :) -* Improve memory and time management for database extraction -* Add error messages if it is impossible to read/delete/modify files -* Add time and memory management for constrained configuration -* Improving zip decompression and path -* Correction of a bug that occurs when server refuse to access / directory "open_basedir" restriction -* Update of the core - -= 1.0.1 = -* First release in the wild web (enjoy) - -== Frequently Asked Questions == - -= Forced backup never ends (but there is no displayed error) = - -Be sure to stay on the configuration page : if you quit the page, the forced backup process will be killed ! - -= Scheduled backup is stucked = - -Scheduled backup only works on website that have traffic. - -Indeed, each visits triggers a piece of the backup process. - -Thus, if there is no traffic, the schedule backup process wont't occur. If there is very little traffic, the backup will be very long, etc - -= I have an error message indicating that another backup is running = - -This message may happen if the chunk size is set quite high. For instance, 40 Mo is clearly too big and server server configuration of many webhosters will kill scripts which use too much memory. - -Most of the case 5Mo is ok. - -If you get this error, set the chunk size to 1Mo and if it solves your problem, increase this chunk size. - -= Compatible Archive Software = - -The backup will be in a multi-part format. In order to uncompress it, you should put all the backup in the same folder and open the .zip file with Winzip. - -You may experience some "corruption" error. It is mainly due that archive software are not compatible with multi-part archives. I have tried with success: - -* Winzip (version 16.0 tested), -* WinRar (some issue with UTF8 characters), and -* IZArc (some issue with UTF8 characters). - -= NOT-Compatible Archive Software = - -These software are *not* compatible with multi-part archives: - -* 7-zip, and -* the Windows Explorer embedded function. - -Do not hesitate to contact me if you face some issues. - -= To restore the backups = - -* install a fresh version of Wordpress on your server ; -* unzip the backup (actually, the zip file comprises a plurality of files i.e. a multi-part zip (zip, z01, z02, etc.). These files should be saved in a same folder and your zip program (such as IZArc, Winzip, Winrar, ...) will do the job for you... -* If you have configured to save the entire installation, replace all the wordpress files by the one in the zip file and import the SQL files (at the root of the zip file, the files named *.sql1, *sql2, etc.) in your database (with for instance phpmyadmin). It is recommended to save your database first ; -* In other cases, replace the 'plugins', 'themes', 'uploads' folders (in the wp-content folder) with the one in the archive, replace the wp-config.php (at the root of your wordpress repository) with the one at the root of the zip file and import the SQL files (at the root of the zip file, the files named *.sql1, *sql2, etc.) in your database (with for instance phpmyadmin). It is recommended to save your database first. - -= The backup files are corrupted = - -Be sure that all thz zip files (i.e. .zip, .z01, z02, etc.) are in the same folder. -If you have still this issue, please try with Winzip software. - -* Where can I read more? - -Visit http://www.sedlex.fr/cote_geek/ - - -InfoVersion:f450b43eebb7570fb1ec0ce188b82e8eebae57cd diff --git a/spec/samples/common/models/wp_item/versionable/beta1.txt b/spec/samples/common/models/wp_item/versionable/beta1.txt deleted file mode 100644 index 5c6057e3..00000000 --- a/spec/samples/common/models/wp_item/versionable/beta1.txt +++ /dev/null @@ -1,8 +0,0 @@ -Contributors: Ramoonus -Donate link: http://www.ramoonus.nl -Tags: Glow, javascript, bbc, -Requires at least: 3.9 -Tested up to: 4.1 -Stable tag: 2.0.0-beta1 - -This plugin adds BBCs Glow Javascript library to your set-up. \ No newline at end of file diff --git a/spec/samples/common/models/wp_item/versionable/blog-reordering.txt b/spec/samples/common/models/wp_item/versionable/blog-reordering.txt deleted file mode 100644 index ca43f7d4..00000000 --- a/spec/samples/common/models/wp_item/versionable/blog-reordering.txt +++ /dev/null @@ -1,22 +0,0 @@ -=== Blog Reordering === -Contributors: The HungryCoder -Donate link: http://hungrycoder.xenexbd.com/payme -Tags: blog, ordering, reordering, arrangment, sorting -Requires at least: 2.6.2 -Tested up to: 2.6.5 -Stable Tag: - -Rearrange you blog ordering. - -== Description == - -Reorder your blog posts in multiple ways including custom ordering instead of typical datewise post display. You can also mark any post as sticky that will be always placed at top. - -== Installation == -This plugin is yet to finalize. Please do not install in live sites. - -1. Upload archive to the `/wp-content/plugins/` directory and unzip. -2. Activate the plugin through the 'Plugins' menu in WordPress -3. Make your ordering settings from Settings -> Blog Reordering - -I am new to SVN. pardon my mistakes. diff --git a/spec/samples/common/models/wp_item/versionable/changelog_version.txt b/spec/samples/common/models/wp_item/versionable/changelog_version.txt deleted file mode 100644 index 96366718..00000000 --- a/spec/samples/common/models/wp_item/versionable/changelog_version.txt +++ /dev/null @@ -1,70 +0,0 @@ -=== Like This === -Contributors: RosemarieP -Tags: karma, likes, post -Requires at least: 3.0 -Tested up to: 3.1 -Stable tag: trunk - -A simple 'I like this' plugin inspired by the facebook 'like' functionality. - -== Description == -A simple 'I like this' plugin inspired by the facebook 'like' functionality. For visitors who don't want to bother with commenting. -http://lifeasrose.ca/2011/03/wordpress-plugin-i-like-this -has a blog entry all about it :) - -A big thanks to Dong (ddliuhb@gmail.com) for finding a syntactical error that was causing problems for some people. And thanks to Raphael (ressoosnowdon@googlemail.com) for noticing this error and working hard to figure out what it was. - -== Installation == - -1. Upload the files into a folder named `roses-like-this` to the `/wp-content/plugins/` directory -2. Activate the plugin through the 'Plugins' menu in WordPress -3. Place `` in 'the loop' of your posts wherever you want the 'like this' link to appear. - - -IMPORTANT!!!! -PLEASE MAKE SURE THAT YOUR THEME HAS THE FOLLOWING LINE IN ITS HEADER FILE: -`` - -...Most high quality themes should have this already but if you're writing your own theme or using a custom theme that doesn't include this line, please make sure you include it in header.php, somewhere between `` and `` - -== Frequently Asked Questions == - -= How can I make the 'like this' link look prettier? = - -With CSS :) Here is the code that I use: -`a.done { -background:url("http://yoururl.com/wordpress/plugins/roses-like-this/action_check.png") bottom right no-repeat; -padding-right:18px; -color:#8bcb46; -}` - -= The javascript is not working! = - -IMPORTANT!!!! -PLEASE MAKE SURE THAT YOUR THEME HAS THE FOLLOWING LINE IN ITS HEADER FILE: -`` - -= The javascript is STILL not working!!! = -Do you call get_header() in your theme? This is also needed, although almost certainly there anyway. - -= The javascript is STILL not working AGAIN!!! = -The plugin expects to find the javascript file in a folder called `roses-like-this` under /plugins. So if you have named the folder something else, you're probably getting a 404 error! - -To fix, you can either rename your folder `roses-like-this` OR you can edit the `likethis.php` file and edit line `112` roses-like-this/ to yourfoldername/ - -== Changelog == - -= 1.0 = -* The very first version of this plugin :) - -= 1.01 = -* Made a small change for those of you installing directly from wordpress.org. This changes the default directory from `likeThis` to `roses-like-this` in order to coincide with what wordpress will install. Should lead to less confusion! - -= 1.1 = -* Major bug fix! :) Anyone having an issue where the likeThis link clicking wasn't saving in the database should find it fixed. - -= 1.2 = -* Bug Fix for those having issues with cookies not being saved correctly. - -= 1.3 = -* Added sidebar widget for displaying most liked posts diff --git a/spec/samples/common/models/wp_item/versionable/my_calendar.txt b/spec/samples/common/models/wp_item/versionable/my_calendar.txt deleted file mode 100644 index fce9d06c..00000000 --- a/spec/samples/common/models/wp_item/versionable/my_calendar.txt +++ /dev/null @@ -1,994 +0,0 @@ -=== My Calendar === -Contributors: joedolson -Donate link: http://www.joedolson.com/donate.php -Tags: calendar, dates, times, events, scheduling, event manager, event calendar -Requires at least: 3.0.6 -Tested up to: 3.5.0 -License: GPLv2 or later -Stable tag: trunk - -Accessible WordPress event calendar plugin. Show events from multiple calendars on pages, in posts, or in widgets. - -== Description == - -My Calendar provides event management and numerous methods to display your events. The plug-in can support individual site calendars within WordPress Multi-User, or multiple calendars displayed by categories of or locations for events. - -* [User's Guide available for purchase](http://www.joedolson.com/articles/my-calendar/users-guide/) with extensive assistance in set up and use. -* [Paid plug-in to add front-end event contributions](https://www.joedolson.com/articles/my-calendar/submissions/) - -=Basic Features:= - -* Standard calendar grid or list views of events -* Show events in monthly, weekly, or daily view. -* Mini-calendar view for compact displays (as widget or as shortcode) -* Widget to show today's events -* Widget to show upcoming or past events -* Custom templates for event output -* Limit by category/categories -* Limit by location -* Limit by author -* Disable default CSS and default JavaScript or display only on specific Pages/Posts -* Editable CSS styles and JavaScript behaviors -* Schedule a wide variety of recurring events. -* Individual occurrences of recurring events can be edited individually -* Access to most aspects of My Calendar can be restricted by role. (Adding events, editing events, editing styles, changing settings, etc.) -* Choose which of the following fields you want to enter and display for each event: - * title, - * description, - * event image, - * alternate description, - * event host, - * event category, - * URL, - * registration status (open, closed or irrelevant), - * event location -* Email notification to administrator when events are scheduled or reserved -* Location Manager for storing frequently used venues -* Fetch events from a remote MySQL database. (Sharing events in a network of sites.) -* Import from [Kieran O'Shea's Calendar plugin](http://wordpress.org/extend/plugins/calendar/) -* Integrated Help page to guide in use of shortcodes and template tags - -=Translations= - -Available languages (in order of completeness): -Japanese, Spanish, Danish, Czech, Hindi, Turkish, Dutch, French, Italian, German, Portuguese, Russian, Swedish, Finnish, Basque, Persian - -Visit the [My Calendar translations site](http://translate.joedolson.com/projects/my-calendar) to check how complete a translation is. - -Translating my plug-ins is always appreciated. Visit my translations site to start getting your language into shape! - -Translator Credits (in no particular order)*: - -[Ale Gonzalez](http://60rpm.tv/i), [Outshine Solutions](http://outshinesolutions.com), [Jakob Smith](http://www.omkalfatring.dk/),, [globus2008](http://wordpress.org/support/profile/globus2008), Frederic Escallier, Luud Heck, Wim Strijbos, [Daisuke Abe](http://www.alter-ego.jp/), [Alex](http://blog.sotvoril.ru/), Mehmet Koçali, Uwe Jonas, Florian Edelmann, Efva Nyberg, [Sabir Musta](http://mustaphasabir.altervista.org), Massimo Sgobino, Leonardo Kfoury, Alexandre Carvalho, Amir Khalilnejad, [Aurelio De Rosa](http://www.audero.it/), Bayram Dede, Dani Locasati, Dario Nunez, Dirk Ginader, Evren Erten, Flávio Pereira, Francois-Xavier Benard, [Gianni Diurno](http://www.gidibao.net), Giksi, Heinz Ochsner, Kazuyuki Kumai, Liam Boogar, Maks, Mano, Massimo Sgobino, Mohsen Aghaei, Oscar, [Rashid Niamat](http://niamatmediagroup.nl/), Stefan Wikstrom, Thomas Meyer, Vedar Ozdemir, [Vikas Arora](http://www.wiznicworld.com), [Miriam de Paula](http://wpmidia.com.br), [HostUCan](http://www.hostucan.com), [Alex Alexandrov](http://www.webhostingrating.com), [Alyona Lompar](http://www.webhostinggeeks.com), [David Gil Pérez](http://www.sohelet.com), [Burkov Boris](http://chernobog.ru), [Raivo Ratsep](http://raivoratsep.com), [Jibo](http://jibo.ro), [Rasmus Himmelstrup](http://seoanalyst.dk), [kndb](http://blog.layer8.sh/) - -* Translators may not have contributed to this plug-in; but have contributed to my [translation repository](http://translate.joedolson.com). - -== Installation == - -1. Upload the `/my-calendar/` directory into your WordPress plugins directory. - -2. Activate the plugin on your WordPress plugins page - -3. Configure My Calendar using the following pages in the admin panel: - - My Calendar -> Add/Edit Events - My Calendar -> Manage Categories - My Calendar -> Manage Locations - My Calendar -> Settings - My Calendar -> Style Editor - My Calendar -> Behavior Editor - My Calendar -> Template Editor - -4. Edit or create a page on your blog which includes the shortcode [my_calendar] and visit - the page you have edited or created. You should see your calendar. Visit My Calendar -> Help for assistance - with shortcode options or widget configuration. - -== Changelog == - -= 2.1.5 = - -* Bug fix: upcoming events timestamps were converted to UTC. - -= 2.1.4 = - -* Bug fix: weekly view when crossing years jumped to next year -* Bug fix: Upcoming events sorting fix -* Bug fix: Upcoming events count fix -* Bug fix: print stylesheet directory fix. - -= 2.1.3 = - -* Bug fix: My Calendar stripped title elements from singular posts unless an SEO plug-in was installed. - -= 2.1.2 = - -* Bug fix: Miscounted number of events in upcoming events view when events were multiple days. -* Bug fix: My Calendar URL guessing now only selects from published Pages/posts -* Tweak: Minor change to HTML output in print view -* Added: Option to display current month or current year using Upcoming Events widget. -* Added: Filter to display a custom on single event details pages with settings field to configure that title. (Improves SEO) -* Language updates: Italian, Russian, Basque - -= 2.1.1 = - -* Bug fix: users without 'Approve Event' ability submitted unapproved events even when event approval was disabled. - -= 2.1.0 = - -* Miscellaneous filepath fixes for custom icons -* Fixed filepath issue for custom content directory in loading calendar generator -* Added templating options to RSS feed event format -* Added two new template tags: description_stripped and shortdesc_stripped; returns the description fields with HTML removed. -* Re-organized settings to provide better grouping. -* Removed jumpbox default setting; jumpbox now only configurable via shortcode. -* Bug fix: titles missing in list view when open to details link enabled. -* Bug fix: Multi-day events listed only once in upcoming events lists. -* Minor stylesheet tweaks. - -= 2.0.12 = - -* I horribly screwed up the Upcoming Events widget in 2.0.11. Please accept my apologies. - -= 2.0.11 = - -* Fixed Broken custom stylesheets editing/selection. -* Added Custom links for widget title links -* Fixed issue with event links expiring immediately -* Fixed issue with holiday collisions restricted in Upcoming Events/events only when holiday category is displayed. -* Added full year output option for iCal downloads. -* Added setting for calendar heading month formatting. -* Updated language files: Japanese, Italian, German, Turkish - -= 2.0.10 = - -* Updated Japanese, Turkish, and Italian translations -* Bug fix: Upcoming Events list could not be limited to a single author. -* Bug fix: Un-approved events were being displayed in some public contexts. -* Bug fix: Problem with RSS feed template elements not rendering in some cases. -* Bug fix: Upcoming Events removed events inappropriately in certain situations when 'skip on holidays' was checked -* Bug fix: Updated method for getting current plugin URL. -* Deprecated support for WordPress versions before 3.0.6. - -= 2.0.9 = - -* Bug fix: Email notification on event addition to admin did not receive event data. -* Bug fix: Accidentally eliminated weekend class. Now it's back! -* Bug fix: Events crossing multiple dates need per-date unique IDs -* Code change: Some code simplification for current URL and plugin URL references. -* Updated languages: Portuguese, Dutch, Italian - -= 2.0.8 = - -* Re-written (simplified) holiday exclusion mechanism. -* Performance improvements to templating and event processing. -* Bug fix: Import from Kieran's "Calendar" plug-in was broken. -* Bug fix: 'nextmonth' class was attached to events in weekly view; not appropriate to view. -* Bug fix: Deleting single instance deleted entire event series. -* Added option: number of events per page in admin events list - -= 2.0.7 = - -* Bug fix: Show list view on mobile devices option did not work. -* Bug fix: No longer forcing links on titles in list or mini view. -* Bug fix: All-day events came up with random end times. -* Change: All-day checkbox added. -* Change: All-day events automatically forced to hide end times. -* Change: removed X-WR-CALNAME field from iCal output for improved compatibility -* Updates: Partial updates to Spanish, Italian, and Dutch translations. - -= 2.0.6 = - -* Bug fix: Mini calendar links pointed to current display month regardless of current display date. -* Bug fix: if day parameter was set, the main calendar views showed events for month starting from that date. -* Bug fix: if day view was targeted from mini calendar with default cid parameter set, would not react -* Bug fix: Calendar could not show events which had start and end dates which spanned the displayed period but were not included in the displayed period. -* Moved screenshots into assets folder in version repository. -* Translation source updated at http://translate.joedolson.com/ - now the translations need refreshing! - -= 2.0.5 = - -* Bug fix: Date links were eliminated in mini calendar if option to link to day-view was enabled. -* Bug fix: Today's events drew events based on UTC instead of current timezone. - -= 2.0.4 = - -* Bug fix: template variable misassigned in the Today's Events shortcode. -* Change: Added option to output iCal either in UTC or with times as entered. (Previously only UTC) - -= 2.0.3 = - -* Bug fix: Upcoming events widget did not support the "show_today's events" option correctly. -* Bug fix: Was not possible to set 12:00 am as the end time for an event. -* Bug fix: prevented blank title in main calendar due to faulty template. - -= 2.0.2 = - -* Bug fix: My Calendar did not enqueue jQuery -* Bug fix: Grid view did not display last day of month if first day of week and last day of month were both Sunday - -= 2.0.1 = - -* Bug fix: Error in default settings for event titles. -* Bug fix: Single Event iCal export broken -* Bug fix: Today's Events shortcode broken if author not specified -* Change: Deleting or updating categories now refreshes the cache. - -= 2.0.0 = - -* Completely re-written database model for events. -* Added: pagination on event manager list of events. -* Added: Restrict groups manager lists to currently grouped/ungrouped lists of events. -* Added links to other event instances visible when editing events with multiple instances. -* Added default category selection. -* Added feature: limit calendar views by event author. -* Added feature: filter event manager view by location, author, or category. -* Added feature: mark categories as private, to only show those events to logged-in users. -* Added templating to locations list so user can produce list of any set of location data. -* Added option in event manager to copy location data into Locations table -* Added [my_calendar_event] shortcode to fetch information for a single event. -* Added template tag {timerange} to display start-end times. -* Change: all events now have an end time. Option to hide end times to maintain current display. -* Bug fix: iCal had missing newline; events now return labeled UTC time -* Bug fix: RSS does better job of clearing non-XML special characters. -* Bug fix: If preset location was selected, no other edits to locations could be done. -* Bug fix: when copying an event, the new event was grouped in the same group as the source event. -* Bug fix: if stylesheet was disabled, stylesheet was erased on next save of style settings. -* Bug fix to category limiting which matched category names like 'baseball' to show 'all' categories. - -= 1.11.3 = - -* Fatal error in PHP 5.4+ https://bugs.php.net/bug.php?id=54657 -* Bug fix: {date} and {time} template tags not rendered in details link when run in a template. -* Bug fix: upgrade database button placement off-screen -* Bug fix: layout on stylesheet editor caused usability problems -* Bug fix: added line break in iCal output. -* Change: added alt attribute to category icons in appropriate contexts. -* [My Calendar 2.0 beta](http://downloads.wordpress.org/plugin/my-calendar.2.0.0.zip) added to subversion repository. Here there be bugs. - -= 1.11.2 = - -* Bug fix: Called wp_editor on versions below 3.3 -* Bug fix: assorted PHP notices cleaned up. - -= 1.11.1 = - -* HTML validation issue fixed in calendar output. -* Added option to hide display of external event links in calendar output. -* Bug fix: Mini calendar should not toggle from mini view when main view switched. -* Bug fix: Week time frame of list view did not return the 'no events' message. -* Feature: No events message can be customized by using an enclosing shortcode: [my_calendar]No events this week![/my_calendar] - -= 1.11.0 = - -* Added option to use {date} in Today's Events widget title. -* Events with the same time are now sub-sorted by title in Upcoming Events lists. -* Template tag {endtime} returns empty string if same as start time -* Standard event output returns empty string for event end time if same as start time. -* Can only check 'multi-day event' option if event has multiple occurrences. -* Categories in editor now sortable by either ID or category name. -* Categories in input now sorted by category name. -* Updated mobile detection class. -* Major revision to permissions handling to use custom capabilities -* Redesign of settings pages. -* Can target tablet devices with CSS by adding a stylesheet called mc-tablet.css to your theme directory. -* Can target other mobile devices with CSS by adding a stylesheet called mc-mobile.css to your theme directory. -* Template tags now support before and after attributes: {tag before="<p>" after="</p>"} -* Added option to retrieve events, categories, and locations from a remote database. (e.g., to share calendar information between 3 related sites.) -* Eliminated details arrow; forcing anchor element on clickable title. -* Added 'id' attribute to My Calendar shortcode, to customize unique ID for calendar and avoid non-compliant duplication of IDs -* Added 'template' attribute to My Calendar shortcode, so specific calendars can use their own individual custom templates. Templates should be text files (.txt) placed in your theme directory. -* Reduced specificity in stylesheets by eliminating ID-based references. -* Fixed bug with day/date consistency in 5-day grid calendars. -* Added day class to date boxes without dates. -* Jumpbox is now switchable from the shortcode. -* Fixed google maps link to use the correct directions targeting method -* Various changes for WP 3.4 compatibility. -* Updated Danish Translation -* Updated Czech Translation -* Added Hindi Translation - -= 1.10.12 = - -* Bug fix: List format showed all dates, regardless of whether there were events for that date. -* Bug fix: List format showed incorrect classes. -* Bug fix: Pipe separator for categories not supported with caching. -* ARRRRGGGGHHHH!!! I'm sure you're as frustrated about all these little releases as I am. But who wants to sit on known bugs? - -= 1.10.11 = - -* Bug fix: Variable not checked for type threw usort warning. -* Bug fix: Details links rendered incorrect page if linked from a single post location with permalinks not enabled. -* Bug fix: Fixed bug where calendar returned no information if cache reached max size. -* Settings change: Caching is now defaulted to off. - -= 1.10.10 = - -* Bug fix: Upcoming events list did not respect category limits. -* Validation error/bug fix: Date for ID for first of month was incorrect. -* Validation error: unencoded ampersand in iCal link if permalinks disabled. - -= 1.10.9 = - -* Added option to clear cache from settings. -* Bug fix: Error in caching where cache returned false for multi-category limited calendars. -* Bug fix: Error in caching where cache returned false for category limited calendars using category name as delimiter. Thanks to [Antti Palosaari](crope@iki.fi) for reporting this bug and for testing fixes. -* Bug fix: Error notices if user is deleted who is assigned as host of some events. Thanks to Florian Edelmann for reporting this bug and contributing solution. -* Bug fix: Upcoming events in dates mode returned null for cached dates. - -= 1.10.8 = - -* Bug fix: upcoming events list breaks if 'This is a multi-day event' is checked for an event with only a single occurrence. -* Bug fix: Upcoming events caching did not cache correct data. -* Modification: eliminated some extraneous database calls -* Modified: clarifying text edits -* Added: category classes on calendar date cells - -= 1.10.7 = - -* Made 'to' value in Google Maps links a translatable value. -* Feature change: iCal download now respects currently selected month. -* Added a phone number field to the Location manager -* Added a setting to display only the core site's calendar on child sites in multisite mode. -* Added a setting for the link target for mini calendar dates -* Re-wrote labels for URL link target settings fields. -* Bug fix: Location selector did not respect currently selected categories. -* Bug fix: "Add another occurrence" option available in Edit mode, but not functional. Removed option. -* Bug fix: Limiting by categories didn't trim whitespace from category names. -* Bug fix: Fixed RSS/ICS/Print permalinks if PATHINFO permalinks are enabled. -* Improved cache handling. Cache limit relative to amount of memory available to PHP. Cache stores information more efficiently. -* Revised RSS/iCal handling to avoid .htaccess problems. - -= 1.10.6 = - -* Revised template tags so the description tags are run through wpautop(), and added _raw versions which are not. -* Fixed a bug in URL generation so that URLs with ports are correctly constructed. -* Fixed a bug iin Print output which did not allow restriction to multiple categories -* Added option to use {date} in previous/next navigation links to indicate what date set is being navigated to. - -= 1.10.5 = - -* I made a truly bone-headed error in the last update, and I'm not even going to say what. If you didn't notice it, lucky for you! - -= 1.10.4 = - -* In my rush to fix the security issue, I broke an aspect of the event navigation. Apologies for this! Now fixed. - -= 1.10.3 = - -* Incorrectly called wp_kses(). Apologies for the frequent updates! - -= 1.10.2 = - -* Critical security update. Please upgrade promptly. Big thank you to Dean Batha for the bug report. - -= 1.10.1 = - -* Bug fix: undeclared array in widget manager -* Renamed overly-generic constant. - -= 1.10.0 = - -* New feature: option to link dates in mini calendar to separate daily view instead of pop-up. -* New feature: no longer necessary to manually edit behaviors in order to open main calendar event titles to separate page. -* New feature: Ability to define grouped events as a single multi-day event and remove duplicates from events lists (upcoming events and today's events widgets) -* New feature: group-association classes assigned to multi-day events in grid display. -* New template tags: {daterange} and {multidate} for displaying a beginning and ending date range for a single event and for displaying each date in a multi-day event, respectively. -* Week-view calendar caption now editable. -* Added printable version. -* Submit buttons in forms are now duplicated at top and bottom of long editing sections, to improve usability. -* Minor style change to group editor to avoid group list colliding with editor textarea. -* Removed angle brackets from Previous/Next events links. -* Added custom action hooks for event save and event delete -* Added ability to prevent today's events from showing up in upcoming events listings. -* Added categories to iCal output. -* iCal should return times in local time, not in UTC. -* Bug fix: iCal output not correctly encoded -* Bug fix: mc_next_link filter did not exist. -* Bug fix: placed limit on maximum size of cached calendar data. -* Bug fix: Upcoming events list will no longer occasionally display more items than expected. -* Bug fix: menu icon not aware of custom content locations - -= 1.9.8 = - -* This is just a convenience update due to a warning appearing in 1.9.7 that I missed. - -= 1.9.7 = - -* Cache was not cleared when events were approved, rejected, or deleted. -* Fixed bug with slashed characters in time and date formats -* Fixed bug where previous/next links did not work on category pages -* Fixed bug where event description was deleted if edited in groups manager. -* Easydrag.js now respects conditional loading by page ID. -* Small change to upcoming events list: events with an end time specifie and not crossing days will move off the list after they end rather than after they start. - -= 1.9.6 = - -* Fixed bug in Event Manager where information about whether an event was open for registration saved incorrectly. -* Added raw details_link template tag. -* Fixed Google Maps link error when using Long/Lat coordinates. -* Associated image option was not available if HTML editor was enabled. - -= 1.9.5 = - -* Bug fix: Caching of Today's events did not account for category limits -* Bug fix: Upcoming events listed by day duplication - -= 1.9.4 = - -* Bug fix: month-by-day recurring events in upcoming events list -* Bug fix: duplication of events in upcoming events list -* Bug fix: when editing a single event with indefinite recurrences, future events set up without continuing recurrence. -* Function error when data not present fixed. -* Added display of sending name/address for support messages - -= 1.9.3 = - -* Stylesheet saving can write longer files. Solves problem with occasional truncation of stylesheets. -* Added transient caching for calendar events to improve performance, plus other various performance improvements -* Small html output change. -* 1.9.0 made details boxes draggable; made this optional. -* Added plug-in support request form. -* Added updated French translation to 1.9.2 -* Fixed bug with date switcher duplicating/skipping months. -* Updated User's Guide (not included with plug-in) - -= 1.9.2 = - -* Bug fix: Fixed sort error returned by calendar if no events are in array. -* Bug fix: Fixed incorrect URLs for icons in custom directory in category key. -* Bug fix: Caption text did not display. -* Added {date} and {time} to details link text templating. -* Bug fix: Fixed {icon} URL in template output. -* Bug fix: Fixed bug with table layout of dates when weekends are disabled on grid calendar. -* Bug fix: Fixed bug with generation of details link when not using permalinks. -* Bug fix: Fixed bug with HTML editor converting HTML entities. -* Bug fix: Fixed bug where weekly view showed the wrong dates if the current week started in the previous month. - -= 1.9.1 = - -* Bug fix: Incorrect title template tag auto-generated if title template is empty. -* Bug fix: Create events permissions broken -* Bug fix: Host list broken in WordPress versions lower than 3.1 -* Bug fix: My Calendar not using WordPress defaults for customizable date and time settings if not set by user. -* Bug fix: Turning off calendar icons did not turn off icons in key -* Bug fix: details links used current URL instead of stored URL -* Bug fix: default widget settings not loaded on upgrade. -* Bug fix: next/previous links not working on home page if permalinks not set. -* Bug fix: event title shown in date field in list mode was not for the first event of the day. -* Style change: Minor change to my-calendar.css to adjust for the green background on weekends. (Which showed up as the result of a fix to an HTML problem in 1.8.9.) -* Bug fix/Option add: Added option to remove individual iCal link -* Option add: Added option to conceal first event title/number of events with date in list mode. - -= 1.9.0 = - -Additions: - -* template editing for list, grid, mini, and single event output. -* pop-up box is now draggable. -* date format option for grid mode, week view. -* templating for details link text. -* templating for event URL link text. -* location filtering from shortcode. -* image upload option for events -* day class to calendar date headings and cells -* individual instances of repeating events can be edited -* feature to add multiple occurrences of an event simultaneously. (concept from Dave Heitzman) -* feature to mass edit information for groups of events (concept from Dave Heitzman) -* stored URL for locations (contrib by John Colvin) -* recurring daily events on weekdays only (based on contrib by John Colvin) -* optional templating for all event output formats -* individual event occurrence iCal export -* numerous additional template tags -* Option to use custom location filter fields as data control -* Shortcode to generate list of saved locations -* Network administrators can control whether sub-site calendars contribute only to a central calendar, only to their own calendar, or whether site administrators can make that choice. -* Upgrade notice information in dashboard for future upgrades. -* implementation of WordPress text diff to compare your styles and scripts against my current released versions -* Option to skip a defined number of events in upcoming events lists. - -Bug fixes: - -* jump box was displaying in week/grid view. -* some potentially repeatable IDs (code validation). -* 'Administrators see all options' did not work. -* Fixed timestamps on main calendar objects -* Squashed e_notice errors. -* category limiting did not work without permalinks due to GET variable conflict with WordPress core -* Missing nonce in database upgrade routine -* Mini calendar simultaneously displayed single event view when visited. -* Link generation for details view did not work if calendar link parameterized -* Issue with weekdays only calendar if day of week set to start on Sunday -* Issue with retrieval of user-specific settings -* Issue with accessing styles and javascript if My Calendar installed in non-standard directory. -* Problem in Today's Events widget when Holiday restrictions are enabled. - -Changes: - -* replaced all default icons with 24-bit transparent PNGs -* jumpbox output to automatically scope to the oldest dates in the database. -* iCal output changed to output all events for complete current month -* RSS output to prioritze newly added events -* holiday skipping/fifth week customization moved into event manager function -* new 'close' icon for pop-up box; added close icon and scripting to mini calendar pop-up -* copy in several places; updated template tags. -* location lists sorted by location label (contrib by John Colvin) -* Eliminated calendar heading option -* default style resets no longer stored in global variables, instead stored as files. -* Map links now trigger the driving directions dialog in Google Maps -* New default stylesheet, refresh.css - -= 1.8.9 = - -* Fixed bug with database upgrade in multi-user additional calendars -* Fixed bug where calendar picked up current month labeling using current day of the month -* Added French translation - -= 1.8.8 = - -* Fixed bug in locations filtering that disabled feature if user not logged in. -* Re-arranged settings and added notices about options which will be removed in a future release. -* Revised RSS feed to use event permalinks when they are available. - -= 1.8.7 = - -* One very minor change in 1.8.6 caused some plug-in conflicts, so I rolled that change back. Will find another solution to the problem it solved. This change affects very few users. - -= 1.8.6 = - -* Fixed bug with {details} template tag when Upcoming widgets configured as Events -* Location and category filters now do not display forms/lists if there isn't more than one choice. -* Extended details link feature to main calendar output and added to output options. -* Minor changes to time-entry jQuery plug-in to improve usability. -* Updated Japanese translation to 1.8.5 -* Added Russian translation to 1.8.5 - -= 1.8.5 = - -* Another bug fix to monthly-by-day recurrence. -* Fixed minor problem with default template not being visible in widget. -* Fixed 'widget title linked' bug. -* Added Turkish translation by Mehmet Ko&231;ali - -= 1.8.4 = - -* Mini calendar widget had a mis-labeled option field -* Custom User settings for event region didn't function correctly. -* A variety of bug fixes applied to events repeating on a monthly-by-day basis - -= 1.8.3 = - -* Turned on spam flag toggle, which I had commented out and failed to restore... -* Default return false ('not spam') for privileged users when checking Akismet - -= 1.8.2 = - -* Fixed bug with {icon} template tag, for real. -* Fixed RSS missing argument -* Fixed empty list rendering in upcoming events widget - -= 1.8.1 = - -* Fixed bug with region saving on edit of location -* Fixed bug with single-event view receiving date as array -* Fixed bug with {icon} template tag -* Fixed bug with calendar output if user settings are enabled but not applied by user -* Fixed bug with list/grid format toggle -* Fixed bug with upcoming events limited by category names - -= 1.8.0 = - -* Added event region as a location field -* Added time selector and altered calendar range selector. -* Added visual editor for event description textarea. -* Added templating tag to add a link to the single event view. -* Added option to not display weekends in grid format. -* Added unique ID for each event in calendar. -* Added default sort order option for admin events list. -* Added admin events list to screen while editing or copying event. -* Added shortcode generator for Page and Post editor. -* Added spam protection: New events are now checked through Akismet if installed and configured. -* Added category selection shortcode. -* Added mini calendar widget. -* Added external link class. -* Added list/grid view toggle. -* Added mobile detection so mobile devices receive list format without JavaScript for easier reading. -* Added Upcoming Events widget sort order option. -* Added Option to link widget title to main calendar page. -* Change: Minor reorganization of settings page. -* Change: Altered time input to use non-military format time, added JavaScript time input. -* Change: Moved My Calendar menu items into the content menu. -* Change: When calendar is limited by categories, only the displayed categories are listed in the category key. -* Change: If widget title is left blank, widget will have no title. -* Change: Moved translation files into a subdirectory (/lang/) -* Bug fix: hcal dates -* Bug fix: problem where restoring styles referenced out of date styles -* Bug fix: error in primary stylesheet -* Bug fix: issue with month-by-day recurring events when recurrance set at 0 -* Bug fix: issue with end dates when recurrance set at 0 -* Bug fix: DB installed to match WPDB chararacter set and collation. -* Bug fix: turn-of-year page navigation in week view. -* Bug fix: entries not remembered in error condition post -* Updated German Translation to version 1.7.0 (Christopher Schauer) -* Updated German Translation to version 1.7.8 (Uwe Jonas) -* Note: during this update cycle, I received two German translations, and am using the most up to date version. -* Added Swedish Translation to version 1.7.8 - -= 1.7.8 = - -* Bug fix: Behaviors page limits lost on settings refresh -* Bug fix: Fix {enddate} shortcode output. -* Bug fix: iCal output improvements -* Modification: RSS and iCal output are disabled entirely when turned off, rather than just hidden. -* Modification: Added styles for days out of current month - -= 1.7.7 = - -* Bug fix: Upcoming Events widget fault in 'dates' mode. - -= 1.7.6 = - -* Bug fix: Upcoming Events widget in days mode was not offsetting time using GMT reference. (Committed silently in 1.7.5) -* Bug fix: Default template not rendered in Today's Events when template left blank -* Bug fix: Slashes not stripped in category key. -* Bug fix: Upcoming Events widget if no upcoming events -* Bug fix: Error with retrieval of Author's ID -* Fixed some non-translatable text strings -* Logic change: Upcoming Events now bases choice on time rather than date (events happening later today are future, rather than only events happening tomorrow or later.) -* Enhancement: respects custom wp-content location definitions - -= 1.7.5 = - -* Bug fix: Error with upcoming events when selected by dates and holiday skipping enabled. -* Bug fix: Upcoming Events widget title defaulted to 'Today's Events' -* Change: Reversed order of Latitude/Longitude on forms to match Google's implementation. - -= 1.7.4 = - -* Bug fix: Upcoming events templates ran htmlentities on output - -= 1.7.3 = - -* Bug fix: upcoming events substitute text still not appearing in some contexts. -* Bug fix: Today's event substitute text had assignment in place of comparison -* Bug fix: Event location not saved properly on edit if Location Fields are disabled on input -* Bug fix: Fixed date and time issues in iCal output -* Bug fix: Fixed character set issue in RSS output -* Bug fix: Major problem with Holiday category event delimiting -* Danish translation updated to 1.7.0 -* Japanese translation updated to 1.7.1 -* Minor documentation and readme.txt updates -* Added additional fallback settings for widgets -* Fixed minor installation issue with version detection. -* Added CSS hook .nextmonth on dates occurring past the end of the currently displayed month. -* Added check for '#' symbol on hex colors in category management. - -= 1.7.2 = - -* Bug fix: Fixed import from Calendar feature. -* Bug fixed: Upcoming events widget default text fixed -* Italian translation updated to 1.7.0 - -= 1.7.1 = - -* Default setting for custom user location type not set -* Reset for inherit.css styles missing -* Widget shortcodes stripped HTML -* Added a fallback function for exif_imagetype 'cuz some servers don't have it available by default. -* Nonce missing in database upgrade -* Ability to edit text for shortcode fallback (No events text) lost. -* Widget defaults not installed on new installation -* Mini and List jQuery did not prevent default link action -* Changed install action to default User settings to off. - -= 1.7.0 = - -* Fix in AJAX navigation for IE -* Fix in JavaScript to re-activate close button -* Fixed bug with locations list not registering current location type in form mode -* Fixed bug with upcoming events and today's events output when regions limits were set -* Fixed bug with upcoming events producing incorrect dates for events recurring on a specific day of the month. -* Revision of Widgeting setup to offer multi-widget support (will require you to re-setup your widgets) -* Revision of style editor to use external stylesheets. -* Revision of style support to add option for custom stylesheets stored outside of plugin directory -* Added: multiple base stylesheets -* Added: Event markup in hCal format -* Added Weekly mode for list and grid view -* Added RSS and iCal exports for upcoming events (enable and disable in settings) -* Added option to block display of an event if there is an event that day which is in a designated 'Holiday' category. -* Added permission setting to allow non-administrators to edit or delete any event. -* Added Czech translation (to 1.6.3) -* Updated Italian and Danish translations -* Security: Implemented nonces - -= 1.6.3 = - -* Updated jQuery to fix conflicts in previous versions and so behaviors would work with AJAX navigation. Not updated by upgrade; use Behaviors reset to apply. -* Incorporated option to enable AJAX navigation for next/previous navigation. -* Fixed bug with multi-month display in list format where January could not be displayed. -* Revised settings page for clarity. -* Fixed some default settings issues. -* Fixed a bug where the locations lists didn't respect the datatype parameter. -* Added templating to event titles for calendar grid or list output. - -= 1.6.2 = - -* Fixed broken style editor. (The way it was broken was awfully weird...kinda wonder how I did it!) -* Fixed missing div in calendar list output. -* Removed debugging call which had been left from testing. -* Fixed storage of initial settings for user settings (array did not store probably initially.) -* Added Italian translation by [Sabir Musta](http://mustaphasabir.altervista.org) - -= 1.6.1 = - -* Bug fix in event saving - -= 1.6.0 = - -* Feature: User profile defined time zone preference -* Feature: User profile defined location preference -* Feature: Define event host as separate from event author -* Feature: Added ability to hide Prev/Next links as shortcode attribute -* Change: Separated Style editing from JS editing - -= 1.5.4 = - -* Fixed: Bug with permissions in event approval process. - -= 1.5.3 = - -* Fixed: Bug which broke the {category} template tag -* Fixed: Bug which moved extra parameters before the "?" in URLs -* Fixed: Bug which produced an incorrect date with day/month recurring events on dates with no remainder -* Added: Japanese translation by [Daisuke Abe](http://www.alter-ego.jp/) - -= 1.5.2 = - -* Fixed: Bug where event data wasn't remembered if an error was triggered on submission. - -= 1.5.1 = - -* Fixed: Bug where events recurring monthly by days appeared on wrong date when month begins on Sunday. -* Fixed: Bug where events recurring monthly by days appeared on dates prior to the scheduled event start. -* Performance improvement: Added SQL join to incorporate category data in event object -* Added quicktag to provide access to category color and icon in widget templates -* Changed link expiration to be associated with the end date of events rather than the beginning date. -* Updated readme plugin description, help files, and screenshots. - -= 1.5.0 = - -* Added: German translation. -* Updated: Danish translation. -* Added: Administrator notification by email feature [Contributions by Roland] -* Added: Reservations and Approval system for events. [Contributions by Roland] -* Added: Events can be recurring on x day of month, e.g. 3rd Monday of the month. - -= 1.4.10 = - -* Fixed: Failed to increment internal version pointer in previous version. -* Fixed: Invalid styles created if category color set to default. -* Fixed: (Performance) Default calendar view attempted to select invalid category. -* Updated: Danish translation. - -= 1.4.9 = - -* Fixed: Bug where location edits couldn't be saved if location fields were on and dropdown was off -* Fixed: Bug where latitude and longitude were switched on Google Maps links -* Fixed: Bug where map link would not be provided if no location data was entered except Lat/Long coordinates. - -= 1.4.8 = - -* Added: Ability to copy events to create a new instance of that event -* Added: Customization of which input elements are visible separate from what output is shown. -* Fixed: Issue where one JS element could not be fully disabled -* Fixed: Internationalization fault with Today's Events showing events from previous day -* Fixed some assorted text errors and missing internationalization strings. -* Fixed issue where the 'Help' link was added to all plug-in listings. -* Reorganized settings page UI. - -= 1.4.7 = - -* Fixed: Bug where infinitely recurring events whose first occurrence was in the future were not rendered in upcoming events -* Fixed: Bug where infinitely recurring bi-weekly events only rendered their first event in calendar view -* Added: Option to indicate whether registration for an event is open or closed, with customizable text. -* Added: Option to supply a short description alternative to the full description. - -= 1.4.6 = - -* Fixed: Flash of unstyled content prevention scripts weren't disabled when other scripting was disabled. -* Fixed: Categories which started with numerals couldn't have custom styles. -* Fixed: Locations required valid 0 float value to save records on some servers; now supplied by default. - -= 1.4.5 = - -* Fixed a bug with editing and adding locations -* Fixed a bug with error messages when adding categories -* Fixed a bug with identification of current day (again?) -* Added Danish translation (Thanks to Jakob Smith) - -= 1.4.4 = - -* Fixed a bug where event end times tags were not rendered when blank in widget templates -* Fixed a bug with event adding and updating for Windows IIS -* Fixed a bug with international characters -* Reduced number of SQL queries made. -* Moved JavaScript output to footer. -* Improved error messages. -* Significant edits to basic codebase to improve efficiency. -* Fixed bug where full default styles didn't initially load on new installs. -* Re-organized default styles to make it easier for users to customize colors. - -= 1.4.3 = - -* Fixed a bug where event end times were displaying the start time instead when editing. -* Fixed a bug introduced by the mini calendar option which displayed titles twice in list format. -* Fixed a bunch of typos. -* Added a loop which automatically adds the mini calendar styles if you don't already have them. -* Fixed a bug where JS didn't run if the 'show only on certain pages' option was used. -* Added a qualifier for upgrading databases when you haven't added any events. - -= 1.4.2 = - -* Fixed a bug in the widget display code which caused problems displaying multiple categories. - -= 1.4.1 = - -* Database upgrade didn't run for some users in 1.4.0. Added manual check and upgrade if necessary. - -= 1.4.0 = - -* Bug fixed: Today's Events widget was not taking internationalized time as it's argument -* Added end time field for events -* Added option for links to expire after events have occurred. -* Added options for alternate applications of category colors in output. -* Added ability to use My Calendar shortcodes in text widgets. -* Added GPS location option for locations -* Added zoom selection options for map links -* Lengthened maximum length for category and event titles -* Added a close link on opened events details boxes. -* Added an option for a mini calendar display type in shortcode -* Optimized some SQL queries and reduced total number of queries significantly. -* Extended the featured to show CSS only on certain pages to include JavaScript as well. -* Upcoming events widget only allowed up to 99 events to be shown forward or back. Changed to 999. -* Attempted to solve a problem with infinitely recurring events not appearing in upcoming events. Let me know. -* Added setting to change Previous Month/Next Month text. -* Yeah, that's enough for now. - -= 1.3.8 = - -* Fixed problem with CSS editing which effectively disabled CSS unless a specific choice had been made for pages to show CSS - -= 1.3.7 = - -* Aren't you enjoying the daily upgrades? I made a mistake in 1.3.5 which hid text in an incorrect way, causing problems in some contexts. - -= 1.3.6 = - -* Fixed an issue where not having defined Pages to show CSS resulted in a PHP warning for some configs. - -= 1.3.5 = - -* Fix for flash of unstyled content issue. -* Added configuration for time text on events with non-specific time. -* Fixed bug where, in list views with multiple months, events occurring on days which did not exist in the previous month were not rendered. (Such as March 30th where previous month was February.) -* Fixed bug where the multi-month view setting for lists caused previous/next events buttons to skip months in calendar view. -* Added option to disable category icons. -* Added option to insert text in calendar caption/title area, appended to the month/year information. -* Fixed a bug where it was not possible to choose the "Show by days" option in the upcoming events widget. -* Updated documentation to match -* Fixed a bug where upcoming events in Days mode did not display correct date -* Added an option to define text to be displayed in place of Today's Events widget if there are no events scheduled. -* Minor changes to default CSS -* Ability to show CSS and JavaScript only on selected pages. - -= 1.3.4 = - -* Fixed a bug with map link and address display which I forgot to deal with in previous release. - -= 1.3.3 = - -* Fixed bug with upgrade path which caused locations database to be created on every activation (also cause of errors with some other plugins). (Thanks to Steven J. Kiernan) -* Made clone object PHP 4 compatible (Thanks to Peder Lindkvist) -* Corrected errors in shortcode functions for today's events -* Corrected rendering of non-specific time events as happening at midnight in widget output - -= 1.3.2 = - -* Fixed bugs with unstripped slashes in output -* Fixed a bug where users could not add location information in events if they had not added any recurring locations -* Removed requirement that address string must be five characters to display a link - -= 1.3.1 = - -* Corrected incorrect primary key in upgrade path. -* Added version incrementing in upgrade path. - -= 1.3.0 = - -* Fixed a CSS class which was applied to an incorrect element. -* Revisions to the Calendar import methods -* Moved style editing to its own page -* Added JavaScript editing to allow for customization of jQuery behaviors. -* Internationalized date formats -* Shortcode support for multiple categories. -* Shortcode support for custom templates in upcoming and today's events -* Added a settings option to eliminate the heading in list format display. -* Fixed a bug which treated the event repetition value as a string on event adding or updating, not allowing some users to use '0' as an event repetition. -* Made events listing sortable in admin view -* Minor revisions in admin UI. -* Added database storage for frequently used venues or event locations. -* Modified JavaScript for list display to automatically expand events scheduled for today. - -= 1.2.1 = - -* Corrected a typo which broke the upcoming events widget. - -= 1.2.0 = - -* Added shortcodes to support inserting upcoming events and todays events lists into page/post content. -* Added option to restrict upcoming events widgets by category -* More superficial CSS changes -* Added Brazilian Portuguese language files -* Fixed bug where I reversed the future and past variable values for upcoming events widgets -* Fixed bug in multi-user permissions. -* Added feature to look for a custom location for icons to prevent overwriting of custom icons on upgrade. - -= 1.1.0 = - -* Fixed some problems with Upcoming Events past events not scrolling off; hopefully all! -* Fixed some problems with fuzzy interpretations of the numbers of past/future events displayed in Upcoming Events. -* Added Bi-weekly events -* Added restrictions so that admin level users can edit any events but other users can only edit their own events -* Removed character restrictions on event titles -* Revised default stylesheet - -= 1.0.2 = - -* Fixed problems with editing and deleting events or categories in multiblog installation -* Fixed escaping/character set issue -* Fixed issue when blog address and wp address did not match (introduced in 1.0.1) -* Added import method to transfer events and categories from Kieran O'Shea's Calendar plugin - -= 1.0.1 = - -* Added missing template code for event end dates. -* Changed defaults so that styles and javascript are initially turned on. -* Removed function collisions with Calendar -* Fixed bug where My Calendar didn't respect the timezone offset in identifying the current day. -* Fixed bug where multiblog installations in WP 3.0 were unable to save events and settings. -* Added Spanish translation, courtesy of [Esteban Truelsegaard](http://www.netmdp.com). Thanks! - -= 1.0.0 = - -* Initial launch. - -== Frequently Asked Questions == - -= Hey! Why don't you have any Frequently Asked Questions here! = - -Because the majority of users end up on my web site asking for help anyway -- and it's simply more difficult to maintain two copies of my Frequently Asked Questions. Please visit [my web site FAQ](http://www.joedolson.com/articles/my-calendar/faq/) to read my Frequently Asked Questions! - -= This plug-in is really complicated. Why can't you personally help me figure out how to use it? = - -I can! Just not in person. I've written a User's Guide for My Calendar, which you can [purchase at my web site](https://www.joedolson.com/articles/my-calendar/users-guide/) for $23. ($19 if you're not interested in getting updates.) This helps defray the thousand plus hours I've spent in developing the plug-in and providing support. Please, consider buying the User's Guide or [making a donation](https://www.joedolson.com/donate.php) before asking for support! - -= How can visitors to my site submit events? = - -I've written a paid plug-in that adds this feature to My Calendar, called My Calendar: Submissions. You can [buy it at my web site](https://www.joedolson.com/articles/my-calendar/submissions/)! - -== Screenshots == - -1. Calendar using calendar list format. -2. Calendar using monthly calendar format. -3. Event management page -4. Category management page -5. Settings page -6. Location management -7. Style editing -8. Mini calendar -9. Script/behavior editing -10. Template editing - -== Upgrade Notice == - -= 2.0.0 = -Major database redesign. Some new features, including single event view and pagination in events lists. Database update is non-destructive; no data will be deleted. diff --git a/spec/samples/common/models/wp_item/versionable/nextgen_gallery.txt b/spec/samples/common/models/wp_item/versionable/nextgen_gallery.txt deleted file mode 100644 index 37c97b8e..00000000 --- a/spec/samples/common/models/wp_item/versionable/nextgen_gallery.txt +++ /dev/null @@ -1,843 +0,0 @@ -=== NextGEN Gallery === -Contributors: photocrati -Tags:gallery,image,images,photo,photos,picture,pictures,slideshow,flash,media,thumbnails,photo-albums,nextgen-gallery,nextgen -Requires at least: 3.6.1 -Tested up to: 4.0 -Stable tag: trunk -License: GPLv2 - -The most popular WordPress gallery plugin and one of the most popular plugins of all time with over 10 million downloads. - -== Description == - -= WordPress Gallery Plugin = - -NextGEN Gallery is the most popular **WordPress gallery plugin**, and one of the most popular WordPress plugins of all time, with over 10 million downloads. - -It provides a powerful engine for uploading and managing galleries of images, with the ability to batch upload, import meta data, add/delete/rearrange/sort images, edit thumbnails, group galleries into albums, and more. It also provides two front-end display styles (slideshows and thumbnail galleries), both of which come with a wide array of options for controlling size, style, timing, transitions, controls, lightbox effects, and more. - -*The NextGEN Gallery WordPress gallery plugin is now proudly maintained by <a href='http://www.photocrati.com'>Photocrati Media</a>. Special thanks to Alex Rabe who created and maintained NextGEN from 2007 through 2011.* - -**NEXTGEN GALLERY 2.0: MAJOR UPDATE IN JULY 2013.** *We released a major update and overhaul to NextGEN Gallery in July 2013. NextGEN Gallery 2.0 presents a completely reworked interface, both for the central options panel and for adding galleries to pages and posts. It's dramatically more powerful and flexible.* - -**INTRODUCING NEXTGEN GALLERY PRO.** *Along with NextGEN 2.0, we're happy to announce a "Pro" upgrade to NextGEN. NextGEN Pro offers 6 new gallery displays, including Pro Masonry, Pro Filmstrip, Pro Film, Pro Thumbnail Grid, Pro Slideshow, and Pro Blogstyle galleries. It also includes a responsive, fullscreen, mobile-friendly Pro Lightbox with commenting and social sharing for individual images within galleries. And it includes premium one-on-one email support for both NextGEN Gallery and NextGEN Pro.* - -**<a href="http://www.nextgen-gallery.com/nextgen-pro">LEARN MORE ABOUT NEXTGEN PRO</a>** - - -= NextGEN WordPress Gallery Plugin Features = - - -*Upload Galleries* - -* Our WordPress gallery plugin offers diverse and powerful functionality for getting images from your desktop to your website. You can easily upload batches of images via a standard WordPress-style uploader, or upload images via zip file or FTP. NextGEN will automatically import your images meta data. - -*Manage Galleries* - -* Centralized gallery management. Enjoy a single location where you can see and manage all your galleries. -* Edit galleries. Add or exclude images, change gallery title and description, reorder of images, resize thumbnails. -* Thumbnail Management. Turn thumbnail cropping on and off, customize how individual thumbnails are cropped, and bulk resize thumbnails across one or more galleries. -* Edit Individual Images. Edit meta data and image tags, rotate images, and exclude images. -* Watermarks. Quickly add watermarks to batches or galleries of images. -* Albums. Create and organize collections of galleries, and display them in either compact or extended format. - -*Display Galleries* - -* Multiple Gallery Types. Choose between two main display styles: Slideshow and Thumbnail, and allow visitors to toggle between the two. Or display Imagebrowser galleries and Singlepics. -* Slideshow Galleries. Choose from a vast array of options for slideshows, including slideshow size, transition style, speed, image order, and optional navigation bar. -* Thumbnail Galleries. Choose from a wide range of options to customize thumbnail galleries, including 5 different lightboxes for individual images, optional thumbnail cropping and editing, thumbnail styles, captions, and more. -* Single Image Displays. Display and format single images. -* Work with Options Panel or Shortcodes. - -= NextGEN WordPress Gallery Plugin Community & Extensions = - -NextGEN has been the dominant WordPress gallery plugin for years. As a result, there is large and great community of users and developers, as well as a large number of dedicated extension plugins. For a list of extension plugins, just search for NextGEN in the WordPress.org plugin repository, or visit our <a href="http://www.nextgen-gallery.com/nextgen-gallery-extension-plugins/">Complete List of NextGEN Extension Plugins</a>. - -= NextGEN WordPress Gallery Plugin Resources = - -*Visit the NextGEN <a href="http://www.nextgen-gallery.com" target="_blank">WordPress Gallery Plugin</a> official homepage<br> -*Visit the <a href="http://www.nextgen-gallery.com/nextgen-pro" target="_blank">NextGEN Pro official landing page</a><br> -*See <a href="http://www.nextgen-gallery.com/help/" target="_blank">NextGEN Gallery Documentation</a><br> -*Get <a href="http://wordpress.org/tags/nextgen-gallery?forum_id=10" target="_blank">NextGEN Support</a> via the WordPress.org forums<br> -*Get <a href="http://www.nextgen-gallery.com/languages/" target="_blank">Translations</a> for your own language<br> -*See <a href="http://www.photocrati.com/photography-wordpress-themes" target="_blank">WordPress Photography Themes</a> by the same author<br> -*Follow NextGEN Gallery on <a title="Follow NextGEN Gallery on Facebook" href="http://www.facebook.com/NextGENGallery" target="_blank">Facebook</a>, <a title="Follow NextGEN Gallery on Twitter" href="http://twitter.com/NextGENGallery" target="_blank">Twitter</a>, and <a title="Follow NextGEN Gallery on Google +" href="http://plus.google.com/101643895780935290171" target="_blank">Google +</a><br> - - -== Credits == - -Copyright:<br> -Photocrati Media 2012-2013<br> -Alex Rabe 2007-2011 - -This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -** Please note ** - -NextGEN Gallery's flash slideshow option is powered by the JW Image Rotator from Long Tail Video. The Image Rotator is provided free as part of our plugin package thanks to a special arrangement with Long Tail Video. Over time, we will be moving away from reliance on this file. For more information, see the Long Tail Video website: http://www.longtailvideo.com. - -== Installation == - -INSTALLATION: The easiest way to enjoy NextGEN Gallery is to login to you WordPress dashboard, go to Plugins >> Add New, search for NextGEN Gallery, and click to install. You can also download the zip file from this page and upload it from the Plugins >> Add New > Upload page. - -HOW TO USE: Just go to a page or post and click the NextGEN Gallery icon. From our Attach to Post interface, you can create, manage, customize, and display your galleries. You can also manage your galleries and gallery settings from the central options area under the "Gallery" tab on your dashboard menu. - -DOCUMENTATION: See <a href="http://www.nextgen-gallery.com/help/" target="_blank">NextGEN Gallery Documentation</a>. - -That's it ... have fun! For more information, feel free to visit the official website for the NextGEN Gallery <a href="http://www.nextgen-gallery.com" target="_blank">WordPress Gallery Plugin</a>. - -http://www.youtube.com/watch?v=Le_ZsNSuIvM - -== Screenshots == - -1. NextGEN Thumbnail Gallery -2. NextGEN Slideshow Gallery -3. NextGEN Imagebrowser Gallery -4. NextGEN Central Gallery Settings Page -5. NextGEN Other Options Page - Watermarking -6. NextGEN Manage Gallery Page - Edit Thumbnails -7. NextGEN Manage Gallery Page - Edit Image Tags -8. NextGEN Interface for Adding Galleries to a Page or Post -9. NextGEN NextGEN Placeholder Image When Editing a Page or Post - -== Shortcode == - -NextGEN Gallery 2.0 introduces our new Attach to Post interface, which means you never need to work with shortcodes again if you would prefer not too. - -If you do want to work with shortcodes, we've also introduce a new, more powerful, and more flexible shortcode system with NextGEN Gallery 2.0. - -**<a href="http://www.nextgen-gallery.com/nextgen-gallery-shortcodes">Learn About NextGEN Gallery 2.0 Shortcodes</a>** - -Legacy shortcodes? For reference, we're also maintaining documentation on NextGEN Legacy shortcodes used in NextGEN 1.9.x and earlier. <a href="http://www.nextgen-gallery.com/shortcodes">See more on Legacy shortcodes</a>. - -For more information, feel free to visit the official website for the NextGEN Gallery <a href="http://www.nextgen-gallery.com" target="_blank">WordPress Gallery Plugin</a>. - -== Frequently Asked Questions == - - -= Why are my galleries not opening up in a lightbox after I move my site? = - -This is often due to the URL paths to the CSS and JavaScript files used by the Lightbox Effects not being changed to relevant addresses based on the new site. This article will help sort out this issue if that is the case: <a href="http://www.nextgen-gallery.com/galleries-opening-lightbox/" target="_blank">Why are my galleries not opening up in a lightbox?</a>. - -= Do you have documentation or tutorials? = - -Yes. See <a href="http://www.nextgen-gallery.com/help/" target="_blank">NextGEN Gallery Documentation</a>. - -= Will NextGEN Gallery work with my theme? = - -Part of what makes the NextGEN Gallery WordPress gallery plugin so popular is its flexibility - it works with the vast majority of premium and free themes, without requiring any coding. - - -= Are the galleries flash based? = - -No, NextGEN Gallery uses Javascript (J-Query) based displays to ensure compatibility across the widest range of displays possible. - - -= Are the galleries mobile friendly? = - -Yes, since we use Javascript rather than flash, NextGEN Gallery is compatible with Android, iOS, and Blackberry. As of July 2013, all galleries are responsive. NextGEN Pro also includes a full screen, responsive Pro Lightbox with mobile gesture support. - - -= What is the difference between a gallery and an album? = - -In the simplest of terms, Galleries contain your images and Albums contain your Galleries. Albums act as links and placeholders to quickly and easily navigate your galleries - Galleries will actually display your images. - - -= Can I upload multiple images at once? = - -Yes, you can batch upload entire galleries at a time. - - -= Can I password protect galleries? = - -Yes, WordPress allows you to password protect pages by default - which includes all galleries and content for the entire page. Password protection of pages can be turned on and off at any time, with just a few clicks. - - -= Can I add a watermark to the images/slideshows? = - -Yes, you can add text or image watermarks to your gallery images. - - -= Can I crop thumbnails? = - -Yes, each thumbnail image can be individually adjusted to suit your needs. - - -= Is there pagination for galleries? = - -Yes, and you can adjust the amount of images to be shown on a page at any time. - - -= Can I customize the lightbox? = - -Yes, the lightbox can be configured with multiple options directly from the Dashboard, and there are multiple CSS styles which can be applied and modified as well. - - -= Can I add HTML to the captions? = - -Yes, caption areas are fully HMTL capable. - - -= Can I add an external links to galleries? = - -Since the captions are fully HTML capable, you can add external links and any other type of mark up you wish. - - -= Is NextGEN Gallery available in foreign languages? = - -Yes, the NextGEN Gallery WordPress gallery plugin has been translated into dozens of languages - <a href="http://www.nextgen-gallery.com/languages/" target="_blank">click here to find out more.</a> - - -= More Information = - -For more information, feel free to visit the official website for the NextGEN Gallery <a href="http://www.nextgen-gallery.com" target="_blank">WordPress Gallery Plugin</a>. - - -== Changelog == - -= V2.0.66.33 - 11.24.2014 = -* Fixed: Broken NextGEN Pro ecommerce-related shortcodes -* Fixed: Spanish PO file - -= V2.0.66.31 - 11.21.2014 = -* Fixed: Broken shortcodes with WordPress 4.0.1 - -= V2.0.66.29 - 09.17.2014 = -* NEW: Added skip_excluding_globally_excluded_images property to displayed gallery objects -* Fixed: SQL generation for random image selection -* Fixed: Adjust regex for replacing displayed gallery placeholder images -* Fixed: Removed filters to home_url needed previously for WMPL compatibility -* Fixed: Use canonical redirects when appropriate -* Fixed: Ability to override image files using XML-RPC - -= V2.0.66.27 - 08.18.2014 = -* Fixed: Missing class.frame_communication_option_handerl.php error - -= V2.0.66.26 - 08.18.2014 = -* NEW: Added fault tolerance to bulk action AJAX requests -* Changed: Moved some settings from DB to in-memory -* Fixed: Compatibility with BuddyPress plugin in multisite environments -* Fixed: Ability to find static resources outside of WP_PLUGIN_DIR -* Fixed: Autoupdate conflict with Photocrati Theme -* Fixed: Workaround GoDaddy's throttling of consecutive AJAX requests -* Fixed: Issue with settings manager in multisite enviroments - -= V2.0.66.17 - 08.08.2014 = -* NEW: Added french translations -* Secured: XSS vulnerability in jQuery Plupload Queue (thanks Codevigilant Team) -* Secured: XSS vulnerability in thumbnail/slideshow integration links -* Secured: XSS vulnerability on Manage Albums page - -= V2.0.66.16 - 07.30.2014 = -* NEW: Added new "limit" setting to Slideshow widgets -* NEW: Added a "ngg_routes" action for other plugins to hook into to provide new routes -* NEW: Added NGG_SKIP_LOAD_SCRIPTS constant, which existed in 1.9.x -* NEW: Added NGG_GALLERY_ROOT_TYPE constant. Set to 'content' to load galleries from the content_dir / content_url -* NEW: Bosnian (bs_BA) language thanks to Nevesin Srdoc -* NEW: Chinese (zh_CN) language thanks to Vahi Chen, http://www.vahichen.com -* NEW: Dutch (nl_NL) language thanks to Taeke Kooiker -* NEW: Filipino (fil) language thanks to Find Hold, http://www.findhold.dk/ -* NEW: French (fr_FR) language thanks to Jean-Yves Dumaine & Le Blog de Lise -* NEW: Hungarian (hu_HU) language thanks to Zoltán Varanka -* NEW: Italian (it_IT) language thanks to Jacopo Caggiano, @tizz -* NEW: Russian (ru_RU) language thanks to SnakeD3 -* NEW: Spanish (es_ES) language thanks to Andrew Kurtis at WebHostingHub -* Changed: Updated Czech language thanks to Separatista; additional thanks to Martin Krizek for the original translation who was mistakenly unaccredited -* Changed: "Upgrade to Pro" page has new design, advertises for NextGEN Plus -* Changed: Basic Albums templates now given the image counter P element the class 'ngg-album-gallery-image-counter' (by user request) -* Changed: Gallery widgets now apply height:auto to their element; fixes compatibility with some themes -* Changed: Random galleries should be substantially faster now (1000% or more for large image tables) -* Fixed: Complete WPML compatibility -* Fixed: Disable Buddypress 'bp_do_redirect_canonical' filter as it ruins our routing system -* Fixed: Use plugins_url() content_url() when appropriate rather than just site_url() and home_url() -* Fixed: WP Cron job will remove not only displayed gallery transients, but rendering transients as well -* Fixed: NGG_RENDERING_CACHE_TTL constant is honored properly -* Fixed: If using the caption template for Basic Thumbnails, only show the image caption when appropriate -* Fixed: If NGG is uninstalled, so are it's custom capabilities -* Fixed: Translate "Attach NextGEN Gallery to Post" ATP icon alt text when translations are active -* Fixed: Multisite gallery path tooltip gave a wrong default setting -* Fixed: Flush 'all' caches when pope_module_list setting changes -* Fixed: Don't enqueue related images css in the admin -* Fixed: Basic Slideshows fixes WP creating extraneous P element above the slideshow display -* Fixed: Basic Singlepic will now display images marked 'excluded' in the admin -* Fixed: Admin pages can now update when the "Save" button text has been translated - -= V2.0.66 - 05.20.2014 = -* Secured: Check mime type of image files using a variety of mechanisms - -= V2.0.65 - 05.04.2014 = -* Secured: Limit uploads to images and zips - -= V2.0.63 - 04.29.2014 = -* NEW: Translation ready -* NEW: Including German translation by Roland Stumpp -* NEW: Including Czech translation by Separatista -* NEW: Including Finnish translation by Vesa Tiirikainen -* NEW: WPML / qTranslate support -* NEW: Bundled Browser+ JavaScript library -* NEW: Added NGG_DISABLE_FILTER_THE_CONTENT constant to manage conflicts -* Changed: Moved jquery.nextgen_radio_toggle.js to NextGEN Admin Module -* Changed: Original display settings are passed to secondary display types -* Fixed: Thumbnail dimension calculations are inaccurate by 1px when maintaining aspect ratio -* Fixed: Copy IPTC data from original to new image when creating new sizes / thumbnails -* Fixed: Use correct absolute path when importing images in a multisite environment -* Fixed: Incorrect display of disk space quotas in multisite environments -* Fixed: Removed redundant roles form in multisite environments -* Fixed: Insert Gallery Window support for multisite environments -* Fixed: Incorrect handling of NextGEN Styles in multisite environments -* Fixed: Not honouring NGG_IMPORT_ROOT constant -* Fixed: Fixed inability to edit gallery properties using XMLRPC's edit_gallery method -* Fixed: Alignment issues in Basic Compact Albums caused by subalbums not displaying image 'counter' -* Fixed: Display setting forms compatibility issue with WordPress 3.9 -* Fixed; Compability with jQuery Dialogs in WordPress 3.9 -* Fixed: Maximum entity code should be a displayed gallery property for recent/random sources only -* Fixed: Problems with zlib compression: https://core.trac.wordpress.org/ticket/18525 -* Fixed: Support for web servers which use a document root of '//' -* Fixed: Compatibility with WPML Translation Management -* Fixed: use 'del' for function name in ngg_store.js, 'delete' is a reserved keyword -* Fixed: Enqueue fontawesome only when necessary -* Fixed: Suhosin compatibility issue when overriding PHP memory limit -* Fixed: Handle images of wrong image type correctly when trying to create cropped thumbnails -* Fixed: Datamapper entities not allowed to have properties with a value of 0 -* Fixed: Resource manager is manipulating feeds -* Fixed: Convert absolute urls to relative urls for lightboxes -* Fixed: Start the resource manager as early as we can within the init action -* Fixed: Routing problem for galleries with images named 1.jpg, 2.jpg, 3.jpg, etc. -* Fixed: Added tooltips to basic slideshow settings -* Fixed: Remove CKEditor's NextGEN button, which is incompatible with NextGEN Gallery 2.x - -= V2.0.61 - 04.01.2014 = -* Fixed: Compatibility with WP 3.9 -* Fixed: Exception thrown when using Reset button - -= V2.0.59 - 03.18.2014 = -* Changed: Separated pope_module_list from ngg_options record in options table -* Fixed: Removed code causing jQuery compatibility issues in WP Admin -* Fixed: Allow third-parties to override jQuery with Google's CDN -* Fixed: When resetting the 'jquery' handle, ensure that jquery-migrate is a dependency -* Fixed: Silenced many PHP warnings -* Fixed: Datamapper->count() not returning the correct count -* Fixed: Compatibility with Gravity Forms - -= V2.0.58 - 03.09.2014 = -* Fixed: Reset jQuery to WP defaults when modified by a third-party -* Fixed: Compatibility with WP jQuery Lightbox plugin -* Fixed: Compatibility with Peekaboo theme - -= V2.0.57 - 03.05.2014 = -* NEW: Re-introduced the Reset button -* NEW: Tooltip added for Page Link to functionality -* NEW: Displayed Gallery Triggers moved from NextGEN Pro to NextGEN Gallery (not in use) -* NEW: Added NGG_Store, a client-side persistence layer (not in use) -* NEW: Added NGG_CRON_SCHEDULE constant. Set to the number of seconds between the execution of NextGEN Gallery cron jobs -* NEW: Added NGG_RENDERING_CACHE_TTL constant. TTL measured in seconds. -* NEW: Added NGG_DISPLAYED_GALLERY_CACHE_TTL constant. TTL measured in seconds. -* NEW: Added NGG_DISABLE_LEGACY_SHORTCODES constant. When TRUE, [slideshow] becomes [nggslideshow]. -* NEW: Added Font Awesome, available for NextGEN Gallery extensions -* Changed: Transients are removed every 30 minutes instead of 60 minutes -* Changed: Admin Page & Form components refactored to allow custom POST processing -* Changed: Default path for NEW multisite installations to wp-content/uploads/sites/%BLOG_ID%/nggallery/ -* Fixed: Ability to upload ZIP files on Windows hosts -* Fixed: Support for filenames with non-ASCII characters -* Fixed: Dynamic updates in the Attach to Post interface (interframe communication) -* Fixed: Attach to Post interface freezing in IE11 -* Fixed: Path issues on Windows Servers -* Fixed: Module installer integrity -* Fixed: Database query performance. No more joins to the WP options table -* Fixed: Lightboxes storing absolute paths for static resources -* Fixed: Displayed gallery cache not regularly flushed -* Fixed: SQL query performance problems. Honor max_packet_allowed variable for MySQL -* Fixed: Multiple database queries generated for determining next available image slug -* Fixed: Corrupted MediaRSS feeds -* Fixed: Padding on Gallery Settings and Other Options pages -* Fixed: Routing issues on subdirectory installs -* Fixed: Importing galleries using the Attach to Post Interface -* Fixed: Gallery path calculations on Windows web servers -* Fixed: Sub-album urls not processed correctly -* Fixed: Apply maximum entity count to existing displayed galleries -* Fixed: NextGEN Gallery Thumbnail Widget shouldn't use ImageBrowser effect -* Fixed: Ability to set shuffle parameter for ImageRotator slideshows -* Fixed: PHP warning about HTMLDocument when displaying a SinglePic -* Fixed: Sanitization of gallery title -* Fixed: Home URL now used instead of Site URL in MediaRSS feed -* Fixed: Attach to Post interface broken when WPML is installed -* Fixed: Attach to Post interface instructing browser to cache the page -* Fixed: Watermarking not working in low-memory environments -* Fixed: Maximum images limit not being applied for galleries already created. -* Fixed: Double forward slashes in static urls -* Fixed: Don't sleep when checking if the installer is running -* Fixed: Don't enforce Pope interface contracts -* Fixed: Remove custom table extra records from wp_options table -* Fixed: Scan folder for new images not working -* Fixed: Incorrect page permalink used for "Page Link To" functionality -* Fixed: Pagination broken when Basic Thumbnail gallery on the same page as Basic Album -* Fixed: parse_url() warnings generated for PHP 5.3.3 and earlier -* Fixed: Compatibility with Headway Themes -* Fixed: Compatibility with web servers which don't provide PHP a document root -* Fixed: Third-party incompatibilities caused by the Photocrati Resource Manager -* Fixed: Compatibility with the Flattr plugin -* Fixed: Compatibility with the Weaver II theme -* Fixed: Interface tweaks for WordPress 3.8 - -= V2.0.40 - 11.26.2013 = -* NEW: Added the ability to apply lightbox effects to non-NGG images -* NEW: Added NGG_HIDE_STRICT_ERRORS constant. Define and set to TRUE to hide strict errors -* NEW: Added NGG_IMPORT_ROOT constant. Define and set to TRUE to browse from a custom directory -* NEW: Added NGG_DEBUG constant. Define and set to TRUE to display helpful messages for debugging -* NEW: Each custom table record will have an associated custom post record for expansion -* NEW: Display helpful error messages when there's a problem uploading images -* NEW: Add data-(src|thumbnail|image-id|title|description) attribute to gallery image anchors -* NEW: Variant support for displayed gallery sources. Random images is limited to 5 variations -* Fixed: Excessive creation of transients for random galleries -* Fixed: Many issues prohibiting the ability to upload images -* Fixed: Compatibility with NextGEN Gallery Export Plugin for Adobe Lightroom (thanks Vladimir!) -* Fixed: Sorting in the Attach to Post interface -* Fixed: HTML allowed in gallery/album descriptions -* Fixed: Requests for galleries within albums that have numeric names are broken -* Fixed: Call to a non-member function get() on WP_Query -* Fixed: Ability to sort by Image ID in the Attach to Post interface -* Fixed: Isolate the Attach to Post from implicit third-party script inclusion -* Fixed: Check for the existance of thumbnails when generating urls, and if missing, generate new ones -* Fixed: Compatibility with NextGEN Facebook OpenGraph+ plugin -* Fixed: Various XML-RPC issues -* Fixed: Widgets stylesheet not included -* Fixed: Issue with color not being pre-selected when previewing Watermark -* Fixed: E_NOTICE emitted when cleaning up cached image files -* Fixed: E_NOTICE emitted when viewing display type settings -* Fixed: Typo adjusting pcre.backtrack_limit for shortcodes -* Fixed: Content within the tabs of the Attach to Post interface cut-off -* Fixed: Routing problem which would cause conflicts with different display types on the same page -* Fixed: Broken Dynamic CSS links on GoDaddy -* Fixed: Ability to use HTML in gallery/album descriptions -* Fixed: Sub-album requests conflicting with paginated galleries on the same page -* Merged: Pull request from andreasE (https://bitbucket.org/photocrati/nextgen-gallery/pull-request/6/) - -= V2.0.33 - 10.21.2013 = -* NEW: Requests /ngg_tag/[tagname] will create a displayed gallery -* NEW: Option added to "Import Gallery" tab to use original images -* Fixed: Links are broken on the ngg_tags-sitemap.xml file by WordPress SEO -* Fixed: PHP notice: Attempt to assign property of non-object -* Fixed: Undefined property warnings when using NextGEN Basic Thumbnails -* Fixed: Detect if an applying a transient to a displayed gallery was successful -* Fixed: Compatibility issues with BJ-Lazy-Load and Colorbox -* Fixed: Pagination conflicts for multiple Imagebrowsers on the same page -* Fixed: Ability to display previous exception with debug mode -* Fixed: Tagclouds not working in multisite instances -* Fixed: Load widgets.css when a widget is being used -* Fixed: Installer should remove all instances of the component factory -* Fixed: Widget settings interface not intuitive -* Fixed: Inability to upload images in some Windows host environments -* Fixed: Sorting images/galleries using the Attach To Post interface -* Fixed: Fix detection of HTTPS (pull request by Leonhardt Wille) -* Fixed: Compilation errors of regular expressions -* Fixed: Pro galleries wouldn't display in environments using PHP 5.3.3 or less -* Fixed: Scanning of router slug is now limited to the uri, not the url -* Fixed: Show slideshow link isn't required for thumbnail/imagebrowser integration -* Fixed: WordPress media-upload with 'singlepic' image size -* Fixed: Use target=_blank when the link setting is provided for NextGEN Basic Singlepic -* Fixed: Only display rendering errors if WP_DEBUG is enabled - -= V2.0.31 - 10.03.2013 = -* NEW: Restored AJAX pagination for NextGEN Basic ImageBrowser display type -* Fixed: Compatibility with WordPress Local SEO by Yoast -* Fixed: Inability to upload images if image_slug field was missing in database -* Fixed: Integration of NextGEN Basic Thumbnail and NextGEN Basic Slideshow display types -* Fixed: Photocrati Resource Manager further adjusted to be third-party friendly -* Fixed: Added the ability to find legacy templates in both the child/parent theme directories -* Fixed: JavaScript errors in Attach to Post interface -* Fixed: Router can handle port numbers in urls -* Fixed: Carousel template was linking to NextGEN Basic ImageBrowser view -* Fixed: SQL query generated for displayed galleries using tags as source -* Fixed: 3rd party compat: raise & never lower pcre.backtrack_limit - -= V2.0.30 - 09.25.2013 = -* NEW: Restored the ability to use imagebrowser display type instead of a lightbox effect -* Changed: Displayed galleries are no longer rendered in RSS feeds -* Changed: Removed "Plugin Check" widget from overview page -* Fixed: Silence PHP warnings/errors in an output buffer for AJAX actions -* Fixed: Compatibility issue with WordPress SEO and broken site maps (and large error_logs) -* Fixed: Compatibility issue with AJAX Event Calendar (and possibly others) -* Fixed: Adjusted Photocrati Resource Manager to be third-party friendly -* Fixed: Fixed empty result set for displayed galleries selecting 'All' tags -* Fixed: URL generation for imagebrowser pagination links -* Fixed: Ensure that image meta is imported on creation -* Fixed: Ensure that transients are removed when an external object cache is used -* Fixed: Don't load pluggable.php. This will fix plugin conflicts -* Fixed: In Attach to Post interface, galleries created in one tab weren't showing in another -* Fixed: Don't output frame events cookie for XML-RPC requests - -= V2.0.27 - 09.18.2013 = -* Fixed: Reduce performance impact of purging displayed gallery transients - -= V2.0.25 - 09.18.2013 = -* Reverting to the 2.0.21 codebase, due to major performance issues in 2.0.23 and 2.0.24 - -= V2.0.23 - 09.16.2013 = -* NEW: WP-Cron job to periodically clean-up displayed gallery transients -* NEW: Added "excluded_container_ids" as parameter for ngg_images shortcode -* Fixed: Lightbox effect is honoured by all display types -* Fixed: Highslide displays images from the correct displayed galleries -* Fixed: Ensure that sub-albums display correctly when the word "album" is part of a slug -* Fixed: Ensure that sub-albums display correctly when numerical slugs are used -* Fixed: Related images heading only added when Related Images functionality is enabled -* Fixed: PHP Warning about undefined index when viewing basic albums -* Fixed: AJAX handling is third-party compatible -* Fixed: Image date is no longer overwritten when an image is modified -* Fixed: Fixed issue with displayed galleries using source='tags' -* Fixed: Problem with transient cache not getting flushed properly from Other Options page -* Fixed: Use correct gallery/transient ID when ajax pagination is used - -= V2.0.21 - 09.09.2013 = -* NEW: Multisite support -* Changed: Default image quality set to 100 for generated images -* Changed: Removed dependence on simplehtmldom library -* Fixed: Related images functionality works as it did in 1.9.x -* Fixed: Don't compress inline JavaScript in post/page content -* Fixed: Click-to-advance slideshow behavior for slideshows -* Fixed: Security warnings from VaultPress -* Fixed: View as Slideshow link works with AJAX pagination -* Fixed: Broken links on Overview page -* Fixed: Backup images option -* Fixed: Stylesheet url generated correctly for Windows hosts -* Fixed: Compatibility with NextGen Custom Fields plugin -* Fixed: Compatibility with Adsense Explosion plugin -* Fixed: Suppress wp_footer notices unless WP_DEBUG is set to TRUE - -= V2.0.17 - 08.30.2013 = -Fixed: Match legacy behaviour when changing gallery path, i.e. don't move files - -= V2.0.14 - 08.27.2013 = -* NEW: Added the ability to override thumbnail settings for NextGEN Basic Albums -* NEW: Shortcode Manager API, which ensures that shortcodes are outputted as intended -* Changed: Re-added the ability to select the original image size for widgets -* Fixed: Ensure that stylesheet url returned is correct for Windows hosts -* Fixed: Broken links and lightbox effects with AJAX pagination -* Fixed: Try to ensure that third party plugins don't add content to our dynamic JS -* Fixed: Improved reliability of iframely.js -* Fixed: Ensure that urls are generated correctly in HTTPs environments -* Fixed: Datamapper works correctly in environments where temporary tables aren't supported -* Fixed: Fixed an issue with thickbox loading animation when home url differs from site url - -= V2.0.11 - 08.19.2013 = -* NEW: Added "run_ngg_resource_manager" hook to by-pass our resource manager -* Changed: Removed "Reset & Uninstall" tab, for now -* Fixed: Compatibility with W3 Total Cache. Please flush cache after updating. -* Fixed: Conflicts with Photocrati Theme Galleries -* Fixed: Blank Attach to Post interface window -* Fixed: Fixed ability to change Lightbox Effect settings -* Fixed: Implemented techniques to ensure WP_Query variables aren't overwritten -* Fixed: Enqueuing AJAX JS libraries twice in wp-admin -* Fixed: Encoding issues -* Fixed: PHP warnings caused by accessing unserialized data as array -* Fixed: Fixed installer issues - -= V2.0.7 - 08.09.2013 = -* NEW: New resource manager that fixes many plugin and theme incompatibilities -* NEW: Styles (custom stylesheets) should reside in wp-content/ngg_styles -* NEW: Added option to "Other Options -> Misc" to control maximum images returned -* Secured: Removed default connector for jQuery FileTree library -* Changed: Updated the simplehtmldom library to version 1.5 -* Changed: jQuery is now enqueued at the beginning of every request -* Fixed: Incompatibilities with BuddyPress -* Fixed: Incompatibilities with Events+, bbPress, Custom Permalinks, and many other plugins -* Fixed: Incompcatibilities with Member Access, AMember, Magic Fields, and More Fields -* Fixed: Incompatibilities with Elegant Themes, Oxygen, Responsive, and many other themes -* Fixed: Ensure that gallery images don't have a border by default -* Fixed: Conflict between imagebrowser and album urls -* Fixed: Reverted default gallerypath to wp-content/gallery/ -* Fixed: Upgrade-safe way of overriding Styles -* Fixed: Generation of AJAX url is now based on slug -* Fixed: Restore nggShowGallery and nggShowSlideshow as wrappers to new API -* Fixed: Always use domain as specified by WordPress Site URL -* Fixed: Use WordPress Home URL over Site URL when appropriate -* Fixed: Numerous pagination issues -* Fixed: Adjusted our forms to comply with WordPress Firewalls -* Fixed: Correct use of select2 DOM selector for maximum compatibility -* Fixed: Path and URL calculations for Windows and UNIX environments -* Fixed: Ensure that pluggable.php is loaded at the start of every request -* Fixed: Fancybox: adjust CSS for further box-sizing protection from themes -* Fixed: Use PHP 5.2.1 compatible named pattern matching syntax -* Fixed: Remove usage of __DIR__ constant not supported by PHP 5.2.x -* Fixed: Removed dependency on mb_string PHP module -* Fixed: Allow "No Lightbox" as an option for Lightbox Effects -* Fixed: Warning: "Invalid CRT parameters detected" for Windows environments - -= V2.0 - 07.30.2013 = -* NEW: Improved user experience throughout the plugin, settings and usage. -* NEW: Plupload queue uploader that allows for bulk and zip uploads within the same interface. -* NEW: Complete redesign of the NextGEN options panel -* NEW: Added new interface for adding galleries from pages and posts. -* NEW: Galleries are now mobile friendly and responsive, which is most noticeable with a responsive theme. -* NEW: Streamlined functionality for displaying galleries based on tags. -* NEW: Architecture based on Pope Framework (http://bitbucket.org/photocrati/pope-framework) -* NEW: New shortcode, “ngg_images”, and corresponding Attach to Post interface -* NEW: Galleries have now global and instance settings -* NEW: Support for FastCGI environments -* Changed: Replaces shortcodes with placeholder images, however still supports legacy shortcodes. -* Changed: Introduced new Growl-like notifications -* Changed: The container and it’s images are centered for slideshows -* Changed: NextGEN styles now override vs replace default styles -* Changed: NextGEN legacy templates have been deprecated (but still function) -* FIXED: The ability to use NextGEN image as a Featured Image. -* FIXED: Many bugs and annoyances, such as PHP warnings, errors, etc. - -= V1.9.13 - 06.11.2013 = -* NEW: Slideshows are now centered to their content area -* Secured: Ensure that only logged in users can upload images -* Fixed: Import date is presered are no longer Jan 1 1970 -* Fixed: Removed mention of upgrade.php, which no longer exists - -= V1.9.12 - 02.15.2013 = -* Fixed: jQuery Conflict Detection was trying to dequeue irremovable scripts - -= V1.9.11 - 02.12.2013 = -* NEW: Added the ability to detect JQuery conflicts on NGG Admin Pages and auto-resolve -* Changed: Added "nggalbum" shortcode. Use this when Jetpack is installed. -* Changed: Using natural sorting algorithm for alphanumeric values -* Changed: Database schema is automatically updated when out-of-date -* Fixed: Fixed several incompatibility issues with Jetpack -* Fixed: Empty drop-down for "Page Link To" -* Fixed: Alphabetical image sorting -* Fixed: Compatibility with Arjuna X theme -* Fixed: “Creating default object from empty value” on album page -* Fixed: Compatibility issues with PHP 5.4 on album page -* Fixed: E_DEPRECATED warning when using get_userdatabylogin() function -* Fixed: Removed many E_NOTICE errors -* Fixed: Correct use of register_uninstall_hook across all PHP versions - -= V1.9.10 - 12.18.2012 = -* Fixed: XML-RPC error displayed when authenticating using WordPress 3.5 -* Fixed: Restored compatibility with NextGEN Gallery Export Plugin -* Fixed: Removed some remaining references to database upgrade code -* Fixed: Deleted galleries within an album are handed gracefully without warning messages -* Fixed: Correct use of register_uninstall_hook -* Fixed: CSS and usability issues with the TinyMCE window used to display galleries - -* NEW: JW ImageRotator v3.17 is now bundled with the plugin and used by default. -* Changed: Removed database upgrade code for versions of NextGEN Gallery earlier than 1.9.3 -* Fixed: Compatibility with WordPress v3.5 ( wpdb->prepare() warnings ) -* Fixed: Sorting by filename now produces expected results using a natural sorting algorithm - -= V1.9.8 - 12.05.2012 = -* Secured: Removed bundled version of swfupload. See fix below for SCM information. -* Changed: All transients created by NextGEN are flushed when the plugin is activated. -* Fixed: Our primary SCM is conducted at http://bitbucket.org/photocrati/nextgen-gallery, but was not synchronizing correctly with the WordPress Plugin SVN Repository -* Fixed: The transient adjustment fixes: http://wordpress.org/support/topic/plugin-nextgen-gallery-_transient_ngg_request-entry-in-wp_options - -= V1.9.7 - 11.13.2012 = -* Secured: Removed bundled version of swfupload; using WordPress-bundled version instead for WordPress 3.2 instances -* Changed: Using JQuery UI for the image sorting interface (thanks Tomás Soler) -* Bugfix: Image uploads work in WP 3.2 when using Safari -* Bugfix: Adjusted TinyMCE window to use built-in JavaScript libraries -* Bugfix: Removed Photocrati acquisition announcement -* Bugfix: Fixed incorrect usage of ImageJpeg() function -* Bugfix: Switched from "template_redirect" to "wp_enqueue_script" hook to load scripts and styles - -= V1.9.6 - 07.21.2012 = -* Changed: Implemented workaround for bug found in WordPress SEO, resulting in no images being added to sitemap -* Bugfix: Fixed an issue with users not being able to dismiss the "Photocrati Acquisition Notice" -* Bugfix: Adjusted Javascript for activating social media pages to load on NextGEN Gallery pages only. -* Bugfix: Fixed compatibility issue with Simple Facebook Connect -* Bugfix: Using correct Facebook Page ID in Like button - -= V1.9.5 - 18.07.2012 = -* Changed: Branding changes following Photocrati acquisition (removed donation messages and updated links) -* Secured: Use WordPress-bundled JavaScript libraries for swfobject and swfupload instead of bundling our own -* Bugfix: Adjusted thickbox effect styling to ensure that the lightbox is always displayed in the foreground -* Bugfix: Fixed compatibility issues with Contact Form 7 and other plugins by following WordPress Plugin conventions -* Bugfix: Fixed network-wide activation in WordPress 3.4 -* Bugfix: Plugin is no longer dependent on it's folder name - -= V1.9.3 - 26.02.2012 = -* Bugfix : Ensure to set the slug for "all" albums -* Bugfix : Updated german translation ( THX to Roger Hunziker ) -* Bugfix : Ensure error checking on IPTC array (THX to Kristian Edlund) -* Bugfix : Handle IE8 cached images better in slideshow -* Bugfix : Show album preview image if selected (THX to Kristian Edlund) - -= V1.9.2 - 17.01.2012 = -* NEW : Added more XMLRPC commands (THX to Vladimir Vinogradsky) -* Changed : Rework Post-thumbnail function (THX to Kristian Edlund) -* Bugfix : Check first for valid images on unzip (only Mac OS zip-files) -* Bugfix : Increase z-index for twenty eleven theme -* Bugfix : Support non latin chars in tagcloud -* Bugfix : Allow other tinymce intance -* Bugfix : Better support for WPML translation - -= V1.9.1 - 10.12.2011 = -* Bugfix : Security hardness for untrusted filenames/meta data (THX to Brian St. Pierre) -* Bugfix : Fixed security vulnerability (TXH to Jon Cave) -* Bugfix : Load piclens script via other function -* Bugfix : IE7 script fix for add gallery -* Bugfix : IE7/IE8 width set correctly for edit album autocomplete field - -= V1.9.0 - 27.11.2011 = -* NEW : Keep images transparency for PNG and GIF format -* NEW : Switch to Plupload, support now HTML5 Upload (only with WordPress 3.3) -* NEW : Added client side resize feature (only with WordPress 3.3) -* NEW : Support for gallery templates in album shortcodes [ album id=x template="name" gallery="templatename" ] -* NEW : Added new hook ngg_delete_picture -* Changed : Updated to jQuery Cycle Version 2.9995 -* Changed : Always cache the single pictures, remove option -* Bugfix : Couldn't use bulk operation for search results -* Bugfix : Bugfix for Edit thumbnails under IE 8 + 9 -* Bugfix : Allow empty altext in ngg.editImage -* Bugfix : Various PHP notice fixes -* Bugfix : Resize fix for Shutter effect and mobile Browser -* Bugfix : FTP Import missing slug field into database -* Bugfix : Check also EXIF field "DateTimeOriginal" for timestamp - -= V1.8.4 - 26.10.2011 = -* Bugfix : Fixed security vulnerability (TXH to Alain Schneider) - -= V1.8.3 - 07.08.2011 = -* Changed : Support for simple custom permalink structures (i.e. /%category%/%postname%/) -* Bugfix : Sub-Albums in Albums didn't create the correct link -* Bugfix : AJAX Pagination didn't work anymore -* Bugfix : Adding index.php to home_url() -* Bugfix : Preview picture lost on backend gallery page 2 or higher - -= V1.8.2 - 12.07.2011 = -* Bugfix : Set pagination variables for search result, otherwise update failed -* Bugfix : Update failed for paged galleries since WordPress 3.2 - -= V1.8.1 - 18.06.2011 = -* Bugfix : Special case for pagination, instead of showing page-1, we show the clean url -* Bugfix : Various PHP notice fixes -* Bugfix : Typo in rewrite rules -* Bugfix : Flush rewrite rules during upgrade later - -= V1.8.0 - 12.06.2011 = -* NEW : Full rework of permalink url structure -* NEW : Adding Google Sitemaps for Images (require WordPress SEO plugin by YOAST ) -* NEW : Support for WPML ( WordPress Multilingual Plugin ) -* NEW : Adding support for arrow key in shutter effect (THX to Flyvans) -* NEW : Adding sort operation for galleries overview page -* Changed : Updated pagination to new WP3.1 style -* Bugfix : Create unique slug in a better way -* Bugfix : Rework screen options filter for gallery and image table -* Bugfix : Empty values in XMLRPC update calls are ignored -* Bugfix : Create gallery failed when safe-mode on -* Bugfix : Permalink didn't work in combination with album & imagebrowser - -= V1.7.4 - 15.02.2011 = -* Bugfix : Disallow direct call of ajax file to avoid path disclosure (THX to High-Tech Bridge SA) -* Bugfix : Rework jQuery Cycle slideshow for IE compat reason (THX to Justin Dickenson) -* Bugfix : Resize only larger images in slideshow -* Bugfix : Improved image format detection in gd.thumbnail class (THX to Kupar.b) - -= V1.7.3 - 20.01.2011 = -* NEW : Introduce plugin health check for conflicts with other plugins/themes -* NEW : Adding new XMLRPC method ngg.deleteImage -* NEW : Adding new XMLRPC method ngg.editImage -* Changed : Rework register script for autocomplete feature -* Bugfix : Bugfix for Multisite setup and flash upload -* Bugfix : WP3.1 compat issue, show site admin page only on Multisite installation - -= V1.7.2 - 13.12.2010 = -* Bugfix : Adding images to database require slug (NOT NULL) - -= V1.7.1 - 13.12.2010 = -* Changed : Disable upgrade for PHP4 user -* Changed : Disable colorpicker for option page -* Bugfix : Compat fix for upgrade - -= V1.7.0 - 11.12.2010 = -* NEW : Publish a new post direct from the gallery admin page -* NEW : Added filter hook 'ngg_get_image_metadata' to add more exif/iptc information -* NEW : Adding Autocomplete field to TinyMCE Popup and Album page -* NEW : More methods for XMLRPC interface -* Changed : New hooks for gallery table (THX to Alexander Schneider) -* Changed : Introduce jQuery dialog as new UI element -* Changed : Call TinyMCE window via admin-ajax -* Bugfix : Better support for SSL blogs -* Bugfix : Install/Upgrade failed when table prefix contain captial letters -* Bugfix : Fix validation issues in Media-RSS -* Bugfix : Empty tags in XMP Meta causes PHP error -* Bugfix : Rework load mechanism for slideshow -* Bugfix : Copy meta data when image is copied -* Bugfix : Icon Support for Ozh' Admin Drop Down Menu -* Bugfix : Use correct sort order in slideshow - -= V1.6.2 - 19.09.2010 = -* NEW : Added constant NGG_SKIP_LOAD_SCRIPTS to avoid script load -* Bugfix : Load Tags library with core files -* Bugfix : Slideshow script failed in IE7, load script now in header -* Bugfix : Load slideshow widget always -* Changed : New admin notice for database upgrade -* Changed : Rework crop feature for featured images -* Changed : Use site_url() instead get_option ('siteurl'), required for SSL support - -= V1.6.1 - 08.09.2010 = -* Bugfix : Script load of swfobject.js failed -* Bugfix : Show sideshow also with 1 or 2 images -* Bugfix : Rework null byte check in zip upload - -= V1.6.0 - 07.09.2010 = -* NEW : Wordpress 3.0 Network (Multi-Site) support -* NEW : Integrate jQuery Cycle as NON-Flash slideshow -* NEW : Adding jQuery File Tree for import folder (THX to Sergey Pasyuk ) -* NEW : Added action hook 'ngg_show_imagebrowser_first' on custom request -* NEW : Added filter hook 'ngg_slideshow_size' to resize sildeshow for mobile browser plugins -* Changed : Reorder tabs for upload -* Changed : New menu icon and screen icon (THX to Ben Dunkle) -* Changed : Load frontend libs always -* Changed : Rework of overview page -* Bugfix : Security bugfix for Zip-Upload (THX to Dominic Szablewski) -* Bugfix : Allow JPG, PNG, GIF extension -* Bugfix : New German translation (THX to Martin Kramarz) -* Bugfix : Copy/Move also backup file -* Bugfix : Calculate correct ratio for fix thumbnail size (THX to Alekz Keck) - -= V1.5.5 - 14.06.2010 = -* Bugfix : Compat issue for post thumbnails with WP2.9 -* NEW : Adding more hooks for custom fields plugin - -= V1.5.4 - 14.06.2010 = -* Bugfix : No resize of smaller images -* Bugfix : Compat issues for Post Thumbnails under WP3.0 -* Bugfix : Esc_URL in Media RSS - -= V1.5.3 - 11.04.2010 = -* New : Adding pagination to footer -* Changed : Perpare new filter to replace slideshow -* Bugfix : Remove non-breaking space from navigation -* Bugfix : Pagination of galleries -* Bugfix : Fixed brackets position for old shortcode query -* Bugfix : Slideshow option 'Show next image on click" has wrong default value - -= V1.5.2 - 25.03.2010 = -* Bugfix : XSS security vulnerability (THX to Core Security Advisories Team , Pedro Varangot) -* Bugfix : Missing $wpdb in shortcodes.php - -= V1.5.1 - 23.03.2010 = -* Bugfix : PHP4 compat issue for Add gallery & options page -* Bugfix : Gallery widget can now have a empty title -* Bugfix : Adding correct stripslash for gallery title - -= V1.5.0 - 18.03.2010 = -* NEW : Support for Post thumbnail feature -* NEW : Backup and Recover function for images (THX to Simone Fumagalli) -* NEW : Resize images after upload (THX to Simone Fumagalli) -* NEW : Added a JSON class for fetching galleries in a RESTful way (see xml/json.php) -* NEW : Adding various new capabilities for user roles -* NEW : Auto downloader for translation file -* Changed : Rename query var from slideshow to callback for compat reason with other plugin -* Changed : Convert widget function to new WP structure -* Changed : Include lookup for tags into the backend search -* Changed : Restructure addgallery and settings page to enable custom tabs -* Bugfix : Select album preview from gallery preview pics instead random list -* Bugfix : Keep fix dimension in edit thumbnail operation -* Bugfix : Import meta data didn't work correct for existing images -* Bugfix : Fix onload bug for Chrome 4 in Shutter script -* Bugfix : Remove various PHP notices for a better world -* Removed : Canonical link is now part of Wordpress 2.9 - -== Upgrade Notice == - -= 1.5.5 = -* Compatibility issue for post thumbnails with WP2.9 and WP3.0. No Database changes... diff --git a/spec/samples/common/models/wp_item/versionable/nextgen_gallery_2.txt b/spec/samples/common/models/wp_item/versionable/nextgen_gallery_2.txt deleted file mode 100644 index d59e36b0..00000000 --- a/spec/samples/common/models/wp_item/versionable/nextgen_gallery_2.txt +++ /dev/null @@ -1,460 +0,0 @@ -=== NextGEN Gallery === -Contributors: photocrati -Tags:gallery,image,images,photo,photos,picture,pictures,slideshow,flash,media,thumbnails,photo-albums,nextgen-gallery,nextgen -Requires at least: 3.5 -Tested up to: 3.5.1 -Stable tag: trunk -License: GPLv2 - -The most popular WordPress gallery plugin and one of the most popular plugins of all time with over 6 million downloads. - -== Description == - -= WordPress Gallery Plugin = - -NextGEN Gallery is the most popular **WordPress gallery plugin**, and one of the most popular WordPress plugins of all time, with over 6 million downloads. - -It provides a powerful engine for uploading and managing galleries of images, with the ability to batch upload, import meta data, add/delete/rearrange/sort images, edit thumbnails, group galleries into albums, and more. It also provides two front-end display styles (slideshows and thumbnail galleries), both of which come with a wide array of options for controlling size, style, timing, transitions, controls, lightbox effects, and more. - -*The NextGEN Gallery WordPress gallery plugin is now proudly maintained by <a href='http://www.photocrati.com'>Photocrati Media</a>. Special thanks to Alex Rabe who created and maintained NextGEN from 2007 through 2011.* - - -= NextGEN WordPress Gallery Plugin Features = - - -*Upload Galleries* - -* Our WordPress gallery plugin offers diverse and powerful functionality for getting images from your desktop to your website. You can easily upload batches of images via a standard WordPress-style uploader, or upload images via zip file or FTP. NextGEN will automatically import your images meta data. - -*Manage Galleries* - -* Centralized gallery management. Enjoy a single location where you can see and manage all your galleries. -* Edit galleries. Add or exclude images, change gallery title and description, reorder of images, resize thumbnails. -* Thumbnail Management. Turn thumbnail cropping on and off, customize how individual thumbnails are cropped, and bulk resize thumbnails across one or more galleries. -* Edit Individual Images. Edit meta data and image tags, rotate images, and exclude images. -* Watermarks. Quickly add watermarks to batches or galleries of images. -* Albums. Create and organize collections of galleries, and display them in either compact or extended format. - -*Display Galleries* - -* Two Gallery Types. Choose between two main display styles: Slideshow and Thumbnail, and allow visitors to toggle between the two. -* Slideshow Galleries. Choose from a vast array of options for slideshows, including slideshow size, transition style, speed, image order, and optional navigation bar. -* Thumbnail Galleries. Choose from a wide range of options to customize thumbnail galleries, including 5 different lightboxes for individual images, optional thumbnail cropping and editing, thumbnail styles, captions, and more. -* Single Image Displays. Display and format single images. -* Work with Options Panel or Shortcodes. - -= NextGEN WordPress Gallery Plugin Community & Extensions = - -NextGEN has been the dominant WordPress gallery plugin for years. As a result, there is large and great community of users and developers, as well as a large number of dedicated extension plugins. For a list of extension plugins, just search for NextGEN in the WordPress.org plugin repository, or visit our <a href="http://www.nextgen-gallery.com/nextgen-gallery-extension-plugins/">Complete List of NextGEN Extension Plugins</a>. - -= NextGEN WordPress Gallery Plugin Resources = - -*Visit the NextGEN <a href="http://www.nextgen-gallery.com" target="_blank">WordPress Gallery Plugin</a> official homepage<br> -*View <a href="http://www.nextgen-gallery.com/nextgen-gallery-demos/" target="_blank">NextGEN Gallery Demos</a><br> -*See the <a href="http://www.nextgen-gallery.com/nextgen-gallery-extension-plugins/">Complete List of NextGEN Extension Plugins</a><br> -*Get <a href="http://wordpress.org/tags/nextgen-gallery?forum_id=10" target="_blank">NextGEN Support</a> via the WordPress.org forums<br> -*Get <a href="http://www.nextgen-gallery.com/languages/" target="_blank">Translations</a> for your own language<br> -*See <a href="http://www.photocrati.com/photography-wordpress-themes" target="_blank">WordPress Photography Themes</a> by the same author<br> -*Follow NextGEN Gallery on <a title="Follow NextGEN Gallery on Facebook" href="http://www.facebook.com/NextGENGallery" target="_blank">Facebook</a>, <a title="Follow NextGEN Gallery on Twitter" href="http://twitter.com/NextGENGallery" target="_blank">Twitter</a>, and <a title="Follow NextGEN Gallery on Google +" href="http://plus.google.com/101643895780935290171" target="_blank">Google +</a><br> - - -== Credits == - -Copyright:<br> -Photocrati Media 2012<br> -Alex Rabe 2007-2011 - -This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -** Please note ** - -NextGEN Gallery's flash slideshow option is powered by the JW Image Rotator from Long Tail Video. The Image Rotator is provided free as part of our plugin package thanks to a special commercial license with Long Tail Video. It is NOT released under GNU General Public License, and cannot be redistributed. A free version of the Image Rotator was previously available under a Creative Commons License, but it has been discontinued. Over time, we will be moving away from reliance on this file. For more information, see the Long Tail Video website: http://www.longtailvideo.com. - -== Installation == - -1. Download, upload and install .zip under Plugins >> Add New > Upload, and activate the NextGEN Gallery WordPress gallery plugin. - -2. From your Wordpress Dashboard, go to Gallery > Add Gallery/Images > Follow the on-screen cues. - -3. Go to a post/page, and select the NextGEN Gallery button from the Kitchen Sink. Follow the on-screen cues to select, adjust, and publish your gallery. - -That's it ... have fun! For more information, feel free to visit the official website for the NextGEN Gallery <a href="http://www.nextgen-gallery.com" target="_blank">WordPress Gallery Plugin</a>. - -http://www.youtube.com/watch?v=Le_ZsNSuIvM - -== Screenshots == - -1. Screenshot Admin Area -2. Screenshot Album Selection -3. Screenshot Shutter Effect -4. Screenshot Watermark function -5. Screenshot Flexible template layout -6. Screenshot Show Exif data - -== Shortcode == - -= Examples = - -*Use Image Tags to Create Galleries/Albums* - [ nggtags album=WordPress,Cologne,Ireland ] - -*Display Captions in Thumbnail Galleries* - [ nggallery id=1 template=caption ] - -*Basic Filmstrip Galleries* - [ nggallery id=2 template=carousel images=7 ] - -*Display Exif Data* - [ imagebrowser id=28 template=exif ] - -*Sort Images in a Gallery Based on Their Tags* - [ nggtags gallery=cologne,wordpress,.. ] - -*Add Tag Clouds* - [ tagcloud] - -*Single Pic Options* - [ singlepic id=x w=width h=height mode=web20|watermark float=left|right ] - -*Template Engine for Gallery Types*<br> -[ nggallery id=1 template=sample1 ]<br> -[ nggallery id=1 template=sample2 ]<br> -[ nggallery id=1 template=sample3 ]<br> -[ nggallery id=1 template=sample4 ]<br> -[ nggallery id=1 template=sample5 ]<br> -[ nggallery id=1 template=sample6 ]<br> - -*Integration with Third Party Plugins*<br> -[ monoslideshow id=1 w=450 h=350 ]<br> -[ nggallery id=1 template=galleryview images=0 ]<br> -[ media id=6 width=320 height=240 plugins=revolt-1 ]<br> -[ media id=3 width=320 height=240 plugins=rateit-2 ]<br> - -For more information, feel free to visit the official website for the NextGEN Gallery <a href="http://www.nextgen-gallery.com" target="_blank">WordPress Gallery Plugin</a>. - -== Frequently Asked Questions == - -= Will NextGEN Gallery work with my theme? = - -Part of what makes the NextGEN Gallery WordPress gallery plugin so popular is its flexibility - it works with the vast majority of premium and free themes, without requiring any coding. - - -= Are the galleries flash based? = - -No, NextGEN Gallery uses Javascript (J-Query) based displays to ensure compatibility across the widest range of displays possible. - - -= Are the galleries mobile friendly? = - -Yes, since we use Javascript rather than flash, NextGEN Gallery is compatible with Android, iOS, and Blackberry. - - -= What is the difference between a gallery and an album? = - -In the simplest of terms, Galleries contain your images and Albums contain your Galleries. Albums act as links and placeholders to quickly and easily navigate your galleries - Galleries will actually display your images. - - -= Can I upload multiple images at once? = - -Yes, you can batch upload entire galleries at a time. - - -= Can I password protect galleries? = - -Yes, WordPress allows you to password protect pages by default - which includes all galleries and content for the entire page. Password protection of pages can be turned on and off at any time, with just a few clicks. - - -= Can I add a watermark to the images/slideshows? = - -Yes, you can add text or image watermarks to your gallery images. - - -= Can I crop thumbnails? = - -Yes, each thumbnail image can be individually adjusted to suit your needs. - - -= Is there pagination for galleries? = - -Yes, and you can adjust the amount of images to be shown on a page at any time. - - -= Can I customize the lightbox? = - -Yes, the lightbox can be configured with multiple options directly from the Dashboard, and there are multiple CSS styles which can be applied and modified as well. - - -= Can I add HTML to the captions? = - -Yes, caption areas are fully HMTL capable. - - -= Can I add an external links to galleries? = - -Since the captions are fully HTML capable, you can add external links and any other type of mark up you wish. - - -= Is NextGEN Gallery available in foreign languages? = - -Yes, the NextGEN Gallery WordPress gallery plugin has been translated into dozens of languages - <a href="http://www.nextgen-gallery.com/languages/" target="_blank">click here to find out more.</a> - -= More Information = - -For more information, feel free to visit the official website for the NextGEN Gallery <a href="http://www.nextgen-gallery.com" target="_blank">WordPress Gallery Plugin</a>. - - -== Changelog == - -= V1.9.13 - 06.11.2013 = -* NEW: Slideshows are now centered to their content area -* Secured: Ensure that only logged in users can upload images -* Fixed: Import date is presered are no longer Jan 1 1970 -* Fixed: Removed mention of upgrade.php, which no longer exists - -= V1.9.12 - 02.15.2013 = -* Fixed: jQuery Conflict Detection was trying to dequeue irremovable scripts - -= V1.9.11 - 02.12.2013 = -* NEW: Added the ability to detect JQuery conflicts on NGG Admin Pages and auto-resolve -* Changed: Added "nggalbum" shortcode. Use this when Jetpack is installed. -* Changed: Using natural sorting algorithm for alphanumeric values -* Changed: Database schema is automatically updated when out-of-date -* Fixed: Fixed several incompatibility issues with Jetpack -* Fixed: Empty drop-down for "Page Link To" -* Fixed: Alphabetical image sorting -* Fixed: Compatibility with Arjuna X theme -* Fixed: “Creating default object from empty value” on album page -* Fixed: Compatibility issues with PHP 5.4 on album page -* Fixed: E_DEPRECATED warning when using get_userdatabylogin() function -* Fixed: Removed many E_NOTICE errors -* Fixed: Correct use of register_uninstall_hook across all PHP versions - -= V1.9.10 - 12.18.2012 = -* Fixed: XML-RPC error displayed when authenticating using WordPress 3.5 -* Fixed: Restored compatibility with NextGEN Gallery Export Plugin -* Fixed: Removed some remaining references to database upgrade code -* Fixed: Deleted galleries within an album are handed gracefully without warning messages -* Fixed: Correct use of register_uninstall_hook -* Fixed: CSS and usability issues with the TinyMCE window used to display galleries - -* NEW: JW ImageRotator v3.17 is now bundled with the plugin and used by default. -* Changed: Removed database upgrade code for versions of NextGEN Gallery earlier than 1.9.3 -* Fixed: Compatibility with WordPress v3.5 ( wpdb->prepare() warnings ) -* Fixed: Sorting by filename now produces expected results using a natural sorting algorithm - -= V1.9.8 - 12.05.2012 = -* Secured: Removed bundled version of swfupload. See fix below for SCM information. -* Changed: All transients created by NextGEN are flushed when the plugin is activated. -* Fixed: Our primary SCM is conducted at http://bitbucket.org/photocrati/nextgen-gallery, but was not synchronizing correctly with the WordPress Plugin SVN Repository -* Fixed: The transient adjustment fixes: http://wordpress.org/support/topic/plugin-nextgen-gallery-_transient_ngg_request-entry-in-wp_options - -= V1.9.7 - 11.13.2012 = -* Secured: Removed bundled version of swfupload; using WordPress-bundled version instead for WordPress 3.2 instances -* Changed: Using JQuery UI for the image sorting interface (thanks Tomás Soler) -* Bugfix: Image uploads work in WP 3.2 when using Safari -* Bugfix: Adjusted TinyMCE window to use built-in JavaScript libraries -* Bugfix: Removed Photocrati acquisition announcement -* Bugfix: Fixed incorrect usage of ImageJpeg() function -* Bugfix: Switched from "template_redirect" to "wp_enqueue_script" hook to load scripts and styles - -= V1.9.6 - 07.21.2012 = -* Changed: Implemented workaround for bug found in WordPress SEO, resulting in no images being added to sitemap -* Bugfix: Fixed an issue with users not being able to dismiss the "Photocrati Acquisition Notice" -* Bugfix: Adjusted Javascript for activating social media pages to load on NextGEN Gallery pages only. -* Bugfix: Fixed compatibility issue with Simple Facebook Connect -* Bugfix: Using correct Facebook Page ID in Like button - -= V1.9.5 - 18.07.2012 = -* Changed: Branding changes following Photocrati acquisition (removed donation messages and updated links) -* Secured: Use WordPress-bundled JavaScript libraries for swfobject and swfupload instead of bundling our own -* Bugfix: Adjusted thickbox effect styling to ensure that the lightbox is always displayed in the foreground -* Bugfix: Fixed compatibility issues with Contact Form 7 and other plugins by following WordPress Plugin conventions -* Bugfix: Fixed network-wide activation in WordPress 3.4 -* Bugfix: Plugin is no longer dependent on it's folder name - -= V1.9.3 - 26.02.2012 = -* Bugfix : Ensure to set the slug for "all" albums -* Bugfix : Updated german translation ( THX to Roger Hunziker ) -* Bugfix : Ensure error checking on IPTC array (THX to Kristian Edlund) -* Bugfix : Handle IE8 cached images better in slideshow -* Bugfix : Show album preview image if selected (THX to Kristian Edlund) - -= V1.9.2 - 17.01.2012 = -* NEW : Added more XMLRPC commands (THX to Vladimir Vinogradsky) -* Changed : Rework Post-thumbnail function (THX to Kristian Edlund) -* Bugfix : Check first for valid images on unzip (only Mac OS zip-files) -* Bugfix : Increase z-index for twenty eleven theme -* Bugfix : Support non latin chars in tagcloud -* Bugfix : Allow other tinymce intance -* Bugfix : Better support for WPML translation - -= V1.9.1 - 10.12.2011 = -* Bugfix : Security hardness for untrusted filenames/meta data (THX to Brian St. Pierre) -* Bugfix : Fixed security vulnerability (TXH to Jon Cave) -* Bugfix : Load piclens script via other function -* Bugfix : IE7 script fix for add gallery -* Bugfix : IE7/IE8 width set correctly for edit album autocomplete field - -= V1.9.0 - 27.11.2011 = -* NEW : Keep images transparency for PNG and GIF format -* NEW : Switch to Plupload, support now HTML5 Upload (only with WordPress 3.3) -* NEW : Added client side resize feature (only with WordPress 3.3) -* NEW : Support for gallery templates in album shortcodes [ album id=x template="name" gallery="templatename" ] -* NEW : Added new hook ngg_delete_picture -* Changed : Updated to jQuery Cycle Version 2.9995 -* Changed : Always cache the single pictures, remove option -* Bugfix : Couldn't use bulk operation for search results -* Bugfix : Bugfix for Edit thumbnails under IE 8 + 9 -* Bugfix : Allow empty altext in ngg.editImage -* Bugfix : Various PHP notice fixes -* Bugfix : Resize fix for Shutter effect and mobile Browser -* Bugfix : FTP Import missing slug field into database -* Bugfix : Check also EXIF field "DateTimeOriginal" for timestamp - -= V1.8.4 - 26.10.2011 = -* Bugfix : Fixed security vulnerability (TXH to Alain Schneider) - -= V1.8.3 - 07.08.2011 = -* Changed : Support for simple custom permalink structures (i.e. /%category%/%postname%/) -* Bugfix : Sub-Albums in Albums didn't create the correct link -* Bugfix : AJAX Pagination didn't work anymore -* Bugfix : Adding index.php to home_url() -* Bugfix : Preview picture lost on backend gallery page 2 or higher - -= V1.8.2 - 12.07.2011 = -* Bugfix : Set pagination variables for search result, otherwise update failed -* Bugfix : Update failed for paged galleries since WordPress 3.2 - -= V1.8.1 - 18.06.2011 = -* Bugfix : Special case for pagination, instead of showing page-1, we show the clean url -* Bugfix : Various PHP notice fixes -* Bugfix : Typo in rewrite rules -* Bugfix : Flush rewrite rules during upgrade later - -= V1.8.0 - 12.06.2011 = -* NEW : Full rework of permalink url structure -* NEW : Adding Google Sitemaps for Images (require WordPress SEO plugin by YOAST ) -* NEW : Support for WPML ( WordPress Multilingual Plugin ) -* NEW : Adding support for arrow key in shutter effect (THX to Flyvans) -* NEW : Adding sort operation for galleries overview page -* Changed : Updated pagination to new WP3.1 style -* Bugfix : Create unique slug in a better way -* Bugfix : Rework screen options filter for gallery and image table -* Bugfix : Empty values in XMLRPC update calls are ignored -* Bugfix : Create gallery failed when safe-mode on -* Bugfix : Permalink didn't work in combination with album & imagebrowser - -= V1.7.4 - 15.02.2011 = -* Bugfix : Disallow direct call of ajax file to avoid path disclosure (THX to High-Tech Bridge SA) -* Bugfix : Rework jQuery Cycle slideshow for IE compat reason (THX to Justin Dickenson) -* Bugfix : Resize only larger images in slideshow -* Bugfix : Improved image format detection in gd.thumbnail class (THX to Kupar.b) - -= V1.7.3 - 20.01.2011 = -* NEW : Introduce plugin health check for conflicts with other plugins/themes -* NEW : Adding new XMLRPC method ngg.deleteImage -* NEW : Adding new XMLRPC method ngg.editImage -* Changed : Rework register script for autocomplete feature -* Bugfix : Bugfix for Multisite setup and flash upload -* Bugfix : WP3.1 compat issue, show site admin page only on Multisite installation - -= V1.7.2 - 13.12.2010 = -* Bugfix : Adding images to database require slug (NOT NULL) - -= V1.7.1 - 13.12.2010 = -* Changed : Disable upgrade for PHP4 user -* Changed : Disable colorpicker for option page -* Bugfix : Compat fix for upgrade - -= V1.7.0 - 11.12.2010 = -* NEW : Publish a new post direct from the gallery admin page -* NEW : Added filter hook 'ngg_get_image_metadata' to add more exif/iptc information -* NEW : Adding Autocomplete field to TinyMCE Popup and Album page -* NEW : More methods for XMLRPC interface -* Changed : New hooks for gallery table (THX to Alexander Schneider) -* Changed : Introduce jQuery dialog as new UI element -* Changed : Call TinyMCE window via admin-ajax -* Bugfix : Better support for SSL blogs -* Bugfix : Install/Upgrade failed when table prefix contain captial letters -* Bugfix : Fix validation issues in Media-RSS -* Bugfix : Empty tags in XMP Meta causes PHP error -* Bugfix : Rework load mechanism for slideshow -* Bugfix : Copy meta data when image is copied -* Bugfix : Icon Support for Ozh' Admin Drop Down Menu -* Bugfix : Use correct sort order in slideshow - -= V1.6.2 - 19.09.2010 = -* NEW : Added constant NGG_SKIP_LOAD_SCRIPTS to avoid script load -* Bugfix : Load Tags library with core files -* Bugfix : Slideshow script failed in IE7, load script now in header -* Bugfix : Load slideshow widget always -* Changed : New admin notice for database upgrade -* Changed : Rework crop feature for featured images -* Changed : Use site_url() instead get_option ('siteurl'), required for SSL support - -= V1.6.1 - 08.09.2010 = -* Bugfix : Script load of swfobject.js failed -* Bugfix : Show sideshow also with 1 or 2 images -* Bugfix : Rework null byte check in zip upload - -= V1.6.0 - 07.09.2010 = -* NEW : Wordpress 3.0 Network (Multi-Site) support -* NEW : Integrate jQuery Cycle as NON-Flash slideshow -* NEW : Adding jQuery File Tree for import folder (THX to Sergey Pasyuk ) -* NEW : Added action hook 'ngg_show_imagebrowser_first' on custom request -* NEW : Added filter hook 'ngg_slideshow_size' to resize sildeshow for mobile browser plugins -* Changed : Reorder tabs for upload -* Changed : New menu icon and screen icon (THX to Ben Dunkle) -* Changed : Load frontend libs always -* Changed : Rework of overview page -* Bugfix : Security bugfix for Zip-Upload (THX to Dominic Szablewski) -* Bugfix : Allow JPG, PNG, GIF extension -* Bugfix : New German translation (THX to Martin Kramarz) -* Bugfix : Copy/Move also backup file -* Bugfix : Calculate correct ratio for fix thumbnail size (THX to Alekz Keck) - -= V1.5.5 - 14.06.2010 = -* Bugfix : Compat issue for post thumbnails with WP2.9 -* NEW : Adding more hooks for custom fields plugin - -= V1.5.4 - 14.06.2010 = -* Bugfix : No resize of smaller images -* Bugfix : Compat issues for Post Thumbnails under WP3.0 -* Bugfix : Esc_URL in Media RSS - -= V1.5.3 - 11.04.2010 = -* New : Adding pagination to footer -* Changed : Perpare new filter to replace slideshow -* Bugfix : Remove non-breaking space from navigation -* Bugfix : Pagination of galleries -* Bugfix : Fixed brackets position for old shortcode query -* Bugfix : Slideshow option 'Show next image on click" has wrong default value - -= V1.5.2 - 25.03.2010 = -* Bugfix : XSS security vulnerability (THX to Core Security Advisories Team , Pedro Varangot) -* Bugfix : Missing $wpdb in shortcodes.php - -= V1.5.1 - 23.03.2010 = -* Bugfix : PHP4 compat issue for Add gallery & options page -* Bugfix : Gallery widget can now have a empty title -* Bugfix : Adding correct stripslash for gallery title - -= V1.5.0 - 18.03.2010 = -* NEW : Support for Post thumbnail feature -* NEW : Backup and Recover function for images (THX to Simone Fumagalli) -* NEW : Resize images after upload (THX to Simone Fumagalli) -* NEW : Added a JSON class for fetching galleries in a RESTful way (see xml/json.php) -* NEW : Adding various new capabilities for user roles -* NEW : Auto downloader for translation file -* Changed : Rename query var from slideshow to callback for compat reason with other plugin -* Changed : Convert widget function to new WP structure -* Changed : Include lookup for tags into the backend search -* Changed : Restructure addgallery and settings page to enable custom tabs -* Bugfix : Select album preview from gallery preview pics instead random list -* Bugfix : Keep fix dimension in edit thumbnail operation -* Bugfix : Import meta data didn't work correct for existing images -* Bugfix : Fix onload bug for Chrome 4 in Shutter script -* Bugfix : Remove various PHP notices for a better world -* Removed : Canonical link is now part of Wordpress 2.9 - -== Upgrade Notice == - -= 1.5.5 = -* Compatibility issue for post thumbnails with WP2.9 and WP3.0. No Database changes... diff --git a/spec/samples/common/models/wp_item/versionable/s2member.txt b/spec/samples/common/models/wp_item/versionable/s2member.txt deleted file mode 100644 index 284e00fd..00000000 --- a/spec/samples/common/models/wp_item/versionable/s2member.txt +++ /dev/null @@ -1,5 +0,0 @@ -Version: 141007 -Stable tag: 141007 - -Tested up to: 4.0 -Requires at least: 3.3 \ No newline at end of file diff --git a/spec/samples/common/models/wp_item/versionable/simple-login-lockdown-0.4.txt b/spec/samples/common/models/wp_item/versionable/simple-login-lockdown-0.4.txt deleted file mode 100644 index 8021a92f..00000000 --- a/spec/samples/common/models/wp_item/versionable/simple-login-lockdown-0.4.txt +++ /dev/null @@ -1,30 +0,0 @@ -=== Simple Login Lockdown === -Contributors: chrisguitarguy -Donate link: http://www.pwsausa.org/ -Tags: security, login -Requires at least: 3.2.0 -Tested up to: 3.3 -Stable tag: 0.4 - -Simple Login Lockdown prevents brute force login attacks/attempts on your WordPress installation. - -== Changelog == - -= 0.1 = -* Proof of concept -* no options page - -= 0.2 = -* New function to get the IP address. -* Added filter to IP for flexibility with proxies, etc. - -= 0.3 = -* small bug fix - -= 0.4 = -* Added plugin options page - -== Upgrade Notice == - -= 04 = -* Dont get attacked! diff --git a/spec/samples/common/models/wp_item/versionable/trunk-version.txt b/spec/samples/common/models/wp_item/versionable/trunk-version.txt deleted file mode 100644 index f9fffb33..00000000 --- a/spec/samples/common/models/wp_item/versionable/trunk-version.txt +++ /dev/null @@ -1,44 +0,0 @@ -=== Simple Login Lockdown === -Contributors: chrisguitarguy -Donate link: http://www.pwsausa.org/ -Tags: security, login -Requires at least: 3.2.0 -Tested up to: 3.3 -Stable tag: trunk - -Simple Login Lockdown prevents brute force login attacks/attempts on your WordPress installation. - -== Description == - -imple login lock down is a way to protect your WordPress blog from brute force login attacks. - -How it works: -1. An attacker attempts to login and fails -2. Simple Login Lockdown record that failed login -3. After a certain number of failed attemps (defaults to five), further attemps to access the wp-login.php page are blocked for a time (defaults to one hour). - -If you happen to forget your password and make a failed login attemp yourself, the plugin will clear out the lockdown count data on successful login. - -Note: This uses $_SERVER['REMOTE_ADDR'] directly. If you're behind a proxy (load balancer, etc), it's not going to work as expected. Eg. Several folks could be attempting logins at once, and all fail. As such, the plugin would pick up on all those requests coming from the same IP -- the load balancer -- and lock the login down. No good. If you're using a load balancer or in some other situation where you're behind a proxy, use this as an example and write your own. Or filter the IP as your desire using `cd_sll_pre_ip`. - -== Installation == - -Install via the WordPress admin or... - -1. Click on the big orange button that says download -2. Unzip the file, and upload the `simple-login-lockdown` folder to your wp-content/plugins directory -3. Login into your website and activate the plugin! - -== Frequently Asked Questions == - -= I got locked out, what do I do? = - -Simple answer: wait. The lockdown will clear in the time you specified, just visit the site again later. - -If you absolutely need to get into your site right now, you can can do one of two things... -1. Fire up your FTP client and rename the `simple-login-lockdown` plugin folder -2. Login into your favorite database administration tool (probably PHPMyAdmin) and search for `locked_down_` in the `option_name` column of the `wp_options` table. Delete the records you find -- they should be "transients". - -== Screenshots == - -1. The plugin options on the Privacy Settings page diff --git a/spec/samples/common/models/wp_item/versionable/wp-maintenance-mode.txt b/spec/samples/common/models/wp_item/versionable/wp-maintenance-mode.txt deleted file mode 100644 index f07eebfd..00000000 --- a/spec/samples/common/models/wp_item/versionable/wp-maintenance-mode.txt +++ /dev/null @@ -1,413 +0,0 @@ -=== WP Maintenance Mode === -Contributors: Designmodo, GeorgeJipa -Plugin Name: WP Maintenance Mode -Plugin URI: http://designmodo.com/ -Author: Designmodo -Author URI: http://designmodo.com/ -Tags: maintenance mode, admin, administration, unavailable, coming soon, multisite, landing page, under construction, contact form, subscribe, countdown -Requires at least: 3.5 -Tested up to: 4.7 -License: GPL-2.0+ - -Adds a splash page to your site that lets visitors know your site is down for maintenance. It's perfect for a coming soon page. - -== Description == - -Add a maintenance page to your blog that lets visitors know your blog is down for maintenance, or add a coming soon page for a new website. User with admin rights gets full access to the blog including the front end. - -Activate the plugin and your blog is in maintenance-mode, works and only registered users with enough rights can see the front end. You can use a date with a countdown timer for visitor information or set a value and unit for information. -Also works with WordPress Multisite installs (each blog from the network has it's own maintenance settings). - -= Features = - -* Fully customizable (change colors, texts and backgrounds); -* Subscription form (export emails to .csv file); -* Countdown timer (remaining time); -* Contact form (receive emails from visitors); -* Coming soon page; -* Landing page templates; -* WordPress multisite; -* Responsive design; -* Social media icons; -* Works with any WordPress theme; -* SEO options; -* Exclude URLs from maintenance. - -= Bugs, technical hints or contribute = - -Please give us feedback, contribute and file technical bugs on [GitHub Repo](https://github.com/Designmodocom/WP-Maintenance-Mode). - -= Credits = - -Developed by [Designmodo](http://designmodo.com) & [StrictThemes – WordPress Themes](http://strictthemes.com/) - -== Installation == - -1. Unpack the download package -2. Upload all files to the `/wp-content/plugins/` directory, include folders -3. Activate the plugin through the 'Plugins' menu in WordPress -4. Go to `Settings` page, where you can change what settings you need (pay attention to **Exclude** option!) - -== Screenshots == - -1. Maintenance Mode example -2. Maintenance Mode example #2 -3. Contact form -4. Dashboard General settings -5. Dashboard Design settings -6. Dashboard Modules settings - -== Frequently Asked Questions == - -= How to use plugin filters = -See [GitHub Repo] (https://github.com/Designmodocom/WP-Maintenance-Mode) FAQ. - -= Cache Plugin Support = -WP Maintenance Mode can be unstable due the cache plugins, we recommend to deactivate any cache plugin when maintenance mode is active. - -= Exclude list = -If you change your login url, please add the new slug (url: http://domain.com/newlogin, then you should add: newlogin) to Exclude list from plugin settings -> General Tab. - -== Changelog == - -= 2.0.9 (29/11/2016) = -* new hook (`wpmm_after_body`) in maintenance mode template (thanks @ [Karolína Vyskočilová](https://github.com/vyskoczilova)) -* pt_PT (portuguese) language update (thanks @ [Pedro Mendonça](https://github.com/pedro-mendonca)) -* maintenance mode template can also be loaded from theme/child-theme folder (thanks @ [Florian Tiar](https://github.com/Mahjouba91) and [Lachlan Heywood](https://github.com/lachieh)) -* new hooks for contact form (if you want to add new fields): `wpmm_contact_form_start`, `wpmm_contact_form_before_message`, `wpmm_contact_form_after_message`, `wpmm_contact_form_end` -* new hook for contact form validation (if you want to validate new fields): `wpmm_contact_validation` -* new hooks for contact form template (if you want to display new fields): `wpmm_contact_template_start`, `wpmm_contact_template_before_message`, `wpmm_contact_template_after_message`, `wpmm_contact_template_end` -* some javascript improvements -* small css fix for contact form (thanks @ [frontenddev](https://wordpress.org/support/topic/please-fix-modal-window-of-contact-form/)) - -= 2.0.8 (09/09/2016) = -* add wp_scripts() function (in helpers.php) to maintain backward compatibility (for those with WP < 4.2.0) -* css fix for subscribe button on maintenance page -* fix multisite administrator access issue -* pt_PT (portuguese) language update (thanks @ Pedro Mendonça) -* new hooks for Contact module: `wpmm_contact_template`, `wpmm_contact_subject`, `wpmm_contact_headers` -* jQuery (google cdn) path fix when SCRIPT_DEBUG is true - -= 2.0.7 (06/07/2016) = -* reset_settings _wpnonce check (thanks # Wordfence) -* modules > google analytics code sanitization (thanks @ Wordfence) -* move sidebar banners from our servers to plugin folder... as WordPress staff requested -* Subscribe button error on Mobile version (thanks @ Hostílio Thumbo) -* replace $wp_scripts global with wp_scripts() function -* de_DE language file update (thanks @ tt22tt) - -= 2.0.6 (20/06/2016) = -* notifications update -* languages update - -= 2.0.5 (17/06/2016) = -* roles (array) fix - -= 2.0.4 (17/06/2016) = -* fixed issue: responsive subscribe form -* fixed issue: jQuery was loaded from a different folder on some WP installations -* fixed issue: errors after update (strstr on empty strings because of saving empty lines on exclude list) -* fixed issue: if "Redirection" from "General" tab is active, also redirects ajax calls -* fixed issue: settings page title was wrong placed -* "contact" feature update - nice email template + reply-to email header -* refactoring for some methods -* all assets are now minified -* rewrite count db records function (used on subscribers count) -* compatible with https://github.com/afragen/github-updater -* compatible with wp-cli http://wp-cli.org/ -* improved responsivity -* improved roles access; now you can set multiple roles (editor, author, subscriber, contributor) and administrator will always have access to backend and frontend -* it_IT translation by benedettogit (https://github.com/benedettogit) -* updated all language files (need help for 100% translation) - - -= 2.0.3 (07/10/2014) = -* WP_Super_Cache issue was fixed -* fixed "Subscribe" button issue on Safari mobile -* fixed color of subscribe-success message (same color as subscribe_text) -* "Social networks" module edits: settings for links target + a new social network: linkedin -* new module "Google Analytics" -* loginform shortcode reintroduced -* dashboard link on maintenance page reintroduced -* the content editor accepts new css inline properties: min-height, max-height, min-width, max-width. Use them wisely! :) -* Settings & sidebar view + old translation files edited -* Update from old version 1.x to 2.x issue was fixed -* Translate on activation issue was fixed -* de_DE translation by Frank Bültge (http://bueltge.github.io/) -* pt_PT translation (100% translated) by Pedro Mendonça (http://www.pedromendonca.pt) -* ru_RU translation (100% translated) by affectiosus (https://github.com/affectiosus) -* nl_NL translation by dhunink (https://github.com/dhunink) -* es_ES translation (100% translated) by Erick Ruiz de Chavez (http://erickruizdechavez.com/) -* fr_FR translation by Florian TIAR (https://github.com/Mahjouba91) -* pt_BR translation by Jonatas Araújo (http://www.designworld.com.br/) -* sv_SE translation by Andréas Lundgren (http://adevade.com/) - -= 2.0.2 (04/09/2014) = -* Removed "Author Link" option from General -* Countdown - save details fix - -= 2.0.1 (02/09/2014) = -* Reintroduced some deprecated actions from old version (but still available in next 4 releases, after that will be removed) and replaced with new ones: -- `wm_head` -> `wpmm_head` -- `wm_footer` -> `wpmm_footer` -* Multisite settings link fix -* WP_Maintenance_Mode: init (array checking for custom_css arrays, move delete cache part into a helper, etc.), add_subscriber, send_contact, redirect fixes & optimizations -* WP_Maintenance_Mode_Admin: save_plugin_settings fixes, delete_cache (new method) -* Settings & Maintenance views fixes -* Readme.txt changes - -= 2.0.0 (01/09/2014) = -* Changed design and functionality, new features -* Changed multisite behaviour: now you can activate maintenance individually (each blog from the network has it's own maintenance settings) -* Removed actions: `wm_header`, `wm_footer`, `wm_content` -* Removed filters: `wm_header` -* Removed [loginform] shortcode -* Some filters are deprecated (but still available in next 4 releases, after that will be removed) and replaced with new ones: -- `wm_heading` -> `wpmm_heading`, -- `wp_maintenance_mode_status_code` -> `wpmm_status_code` -- `wm_title` -> `wpmm_meta_title` -- `wm_meta_author` -> `wpmm_meta_author` -- `wm_meta_description` -> `wpmm_meta_description` -- `wm_meta_keywords` -> `wpmm_meta_keywords` -* Added new filters: -- `wpmm_backtime` - can be used to change the backtime from page header -- `wpmm_meta_robots` - can be used to change `Robots Meta Tag` option (from General) -- `wpmm_text` - can be used to change `Text` option (from Design > Content) -- `wpmm_scripts` - can be used to embed new javascripts files -- `wpmm_styles` - can be used to embed new css files -- `wpmm_search_bots` - if you have `Bypass for Search Bots` option (from General) activated, it can be used to add new bots (useragents) -* Removed themes and now we have a "Design" & "Modules" tabs, where the look and functionality of the maintenance page can be changed as you need - -= 07/07/2014 = -* Switch to new owner, contributor - -= 1.8.11 (07/25/2013) = -* Fixes for php notices in scrict mode -* Alternative for check url, if curl is not installed - -= 1.8.10 (07/18/2013) = -* Add check for urls, Performance topics -* Change default setting of 'Support Link' to false -* Fix network settings php notices - -= 1.8.9 (06/20/2013) = -* Allow empty header, title, heading string -* Small code changes -* Add Support function -* Remove preview, will include later in a new release with extra settings page - -= 1.8.8 (06/05/2013) = -* Fix path to localized flash content -* Fix preview function -* Add ukrainian translation -* Add czech translation -* Fix exclude function for IP -* Security fix for save status via Ajax - -= 1.8.7 (04/07/2013) = -* Add RTL support for splash page -* Add Filter Hook `wp_maintenance_mode_status_code` Status Code; default is 503 -* Add support for custom splash page; leave a file with this name `wp-maintenance-mode.php` in the wp-content; the plugin use this file - The plugin checks in `WP_CONTENT_DIR . '/wp-maintenance-mode.php'` -* Small minor changes -* Add filter for more date on splash page - -= 1.8.6 (02/22/2013) = -* Remove log inside console for JS -* Add support for time inside the countdown -* Add filter hook `wm_meta_author`for the meta data author -* Add filter hook `wm_meta_description` for custom description -* Add filter hook `wm_meta_keywords`for custom meta keys - -= 1.8.5 (01/24/2013) = -* Added new settings for hide, view notices about the active maintenance mode -* Changes on source, codex -* Fix PHP Notices [Support Thread](http://wordpress.org/support/topic/error-message-in-settings-1) -* Change default settings, added ajax -* Fix Preview function -* Fix uninstall in WPMU -* Small updates on styles for login form - -= 1.8.4 (12/06/2012) = -* Fix for include JS in frontend to use countdown -* Small mini fix for a php notice -* Add charset on spalsh page for strange databases -* Enhanced default exclude adresses -* Add shortcode `[loginform]` for easy use a login form in splash page -* Test with WordPress 3.5 - -= 1.8.3 = -* Fix for the forgotten update of JS-files; slow SVN :( -* Minor Fixes - -= 1.8.2 = -* Add different access for Frontend and Backend -* Add Rewrite after Login for Frontend Access -* Different small changes -* Test for WP 3.5 - -= 1.8.1 = -* Add option for value of robots meta tag -* Add option for optional admin login - -= 1.8.0 = -* Include all scripts in backend via function -* Update datepicker and countdown js -* Supportet IP as exclude for see the frontend -* Add support for flish cache od WP Super Cache and W3 Total Cache plugins -* Fix for changes in WP 3.3 Multisite - -= 1.7.1 (12/05/2011) = -* fix for WP smaller 3.2* on Network - -= 1.7.0 (12/02/2011) = -* add functionalities to use in WP Multisite -* remove message in header, current is not fixed the ticked in core and the message on Admin Bar an Notice is enough -* check on WP 3.3RC1 - -= 1.6.10 (08/30/2011) = -* add hint in Admin Bar, if active -* small changes for WP Codex - -= 1.6.9 (06/13/2011) = -* Small fix for empty string on custom design - -= 1.6.8 (04/05/2011) = -* Small changes on check for datepicker -* Fix for Design monster - -= 1.6.7 (01/05/2011) = -* Bugfix: new check for files for different themes; hope this fix the server errors -* Bugfix: fix add default settings -* Maintenance: different changes on the syntax -* Feature: add check for Super Admin on WP Multisite; has allways the rights for access -* Feature: now it is possible to exclude feed from maintenance mode -* Maintenance: check with 3.0.4 and 3.1-RC2 -* Maintenance: update language file: .pot, de_DE -* Bugfix: JavaScript error on Bulk Actions on plugins fixed -* Maintenance: fix all notice, if set no values - -= 1.6.6. (10/09/2010) = -* Maintenance: many changes on the code; $locale and hook in side frontend -* Maintenance: change attribute_escaped to esc_attr with custom method for WP smaller 2.8 -* Maintenance: Update german language files -* Feature: Shortcodes is now possible in the "Text" option -* Feature: no cache header rewrite - -= 1.6.5 (09/16/2010) = -* add new design "Chemistry" by [elmastudio.de](http://www.elmastudio.de/ "elmastudio.de") -* changes for include methods od class for preview -* changes the possibility for include of language specific flash files - -= 1.6.4 (09/13/2010) = -* add preview functions -* bugfix for list in wp-admin/plugins.php -* remove datepicker.regional - dont work fine -* different small changes -* new language file .pot -* add flash file and change on plugin for style "Animate" for spanish language - -= 1.6.3 (07/27/2010) = -* bugfix to include stylesheet on maintenance mode message - -= 1.6.2 (07/08/2010) = -* add functions for hint in the new UI of WP 3.0 -* add more WP Codex standard source -* fix strings in the language and languages files -* add datetimepicker-de - -= 1.6.1 (06/18/2010) = -* fix a problem with https://; see [Ticket #13941](http://core.trac.wordpress.org/ticket/13941) - -= 1.6 (05/17/2010) = -* bugfix for exclude sites - -= 1.5.9 (05/07/2010) = -* change different points -* add possibility to wotk with MySQLDumper - -= 1.5.8 (21/03/2010)= -* fix exclude error -* add textareas for heading and header fields - -= 1.5.7 (03/18/2010) = -* block admin-area via role -* add message for registered users with not enough rights -* add message on login-page -* different changes - -= 1.5.6 (02/25/2010) = -* changes on css, site.php and different syntax on the plugin - -= 1.5.5 (02/23/2010) = -* SORRY, small bug for the url to jQuery - -= 1.5.4 (02/23/2010) = -* add time for countdown -* changes for WP 3.0 -* changees on rights to see frontend - -= 1.5.3 (01/05/2010) = -* Fix for JavaScript with WordPress 2.9 -* Add new custom fields for fronted: title, header, heading -* Fix for setting userrole to see frontend -* Change laguage files - -= 1.5.2 (01/04/2010) = -* add user-role setting -* correctly the de_DE language file - -= 1.5.1 (10/04/2009) = -* add small fix -* add language files (en_ES, ro_RO) - -= 1.5.0 (09/28/2009) = -* add countdown -* change options -* change default options -* add field for own adress to excerpt of the maintenance mode -* etc. - -= 1.4.9 (07/09/2009) = -* also ready for WordPress 2.6 -* add romanian language files -* add italian language file by [Gianni Diurno](http://gidibao.net/ "Gianni Diurno") - -= 1.4.8 (03/09/2009) = -* add design "Damask" by [Fabian Letscher](http://fabianletscher.de/ "Fabian Letscher") -* add design "Lego" by [Alex Frison](http://www.afrison.com/ "Alex Frison") - -= 1.4.7 (26/08/2009) = -* change doc-type to utf-8 without BOM - -= v1.4.6 (24/08/2009) = -* add design "Animate (Flash)" by [Sebastian Schmiedel](http://www.cayou-media.de/ "Sebastian Schmiedel") -* add new hook for add content `wm_content` to include flash on content -* add frensh language files - -= v1.4.5 (19/08/2009) = -* fix html string in text on frontend -* add design "Paint" by [Marvin Labod](http://bugeyes.de/ "Marvin Labod") -* add turkey language files - -= v1.4.4 (18/08/2009) = -* add design "Chastely" by [Florian Andreas Vogelmaier](http://fv-web.de/ "Florian Andreas Vogelmaier") -* add design "Only Typo" by [Robert Pfotenhauer](http://krautsuppe.de/ "Robert Pfotenhauer") - -= v1.4.3 (13/08/2009) = -* add option for the Text -* add option for active maintenance mode -* add design "The FF Error" by [Thomas Meschke](http://www.lokalnetz.com/ "Thomas Meschke") -* add design "Monster" by [Sebastian Sebald](http://www.backseatsurfer.de "Sebastian Sebald") - -= v1.4.2 (10/08/2009) = -* add design "The Sun" by [Nicki Steiger](http://mynicki.net/ "Nicki Steiger") -* now it is possible to add own css and add in settings the url to the css-file - -= v1.4.1 (07/08/2009) = -* small html-fix - -= v1.4 (06/08/2009) = -* complety new code -* options menu -* new designs by [David Hellmann](http://www.davidhellmann.com/ "David Hellmann") diff --git a/spec/samples/common/models/wp_item/versionable/wp-photo-plus-5.1.15.txt b/spec/samples/common/models/wp_item/versionable/wp-photo-plus-5.1.15.txt deleted file mode 100644 index 02ab07f1..00000000 --- a/spec/samples/common/models/wp_item/versionable/wp-photo-plus-5.1.15.txt +++ /dev/null @@ -1,9 +0,0 @@ -=== WP Photo Album Plus === -Contributors: opajaap -Tags: photo, album, photoalbum, gallery, slideshow, sidebar widget, photowidget, photoblog, widget, qtranslate, cubepoints, multisite, network, lightbox, comment, watermark, iptc, exif, responsive, mobile -Stable tag: trunk -Version: 5.1.15 -Author: J.N. Breetvelt -Author URI: http://www.opajaap.nl/ -Requires at least: 3.1 -Tested up to: 3.7.1 \ No newline at end of file diff --git a/spec/samples/common/models/wp_item/versionable/wp_polls.txt b/spec/samples/common/models/wp_item/versionable/wp_polls.txt deleted file mode 100644 index b3425855..00000000 --- a/spec/samples/common/models/wp_item/versionable/wp_polls.txt +++ /dev/null @@ -1,395 +0,0 @@ -=== WP-Polls === -Contributors: GamerZ -Donate link: http://lesterchan.net/site/donation/ -Tags: poll, polls, polling, vote, booth, democracy, ajax, survey, post, widget -Requires at least: 2.8 -Tested up to: 3.7 -Stable tag: trunk - -Adds an AJAX poll system to your WordPress blog. You can also easily add a poll into your WordPress's blog post/page. - -== Description == - -WP-Polls is extremely customizable via templates and css styles and there are tons of options for you to choose to ensure that WP-Polls runs the way you wanted. It now supports multiple selection of answers. - -= Previous Versions = -* [WP-Polls 2.40 For WordPress 2.7.x](http://downloads.wordpress.org/plugin/wp-polls.2.40.zip "WP-Polls 2.40 For WordPress 2.7.x") -* [WP-Polls 2.31 For WordPress 2.5.x And 2.6.x](http://downloads.wordpress.org/plugin/wp-polls.2.31.zip "WP-Polls 2.31 For WordPress 2.5.x And 2.6.x") -* [WP-Polls 2.20 For WordPress 2.1.x, 2.2.x And 2.3.x](http://downloads.wordpress.org/plugin/wp-polls.2.20.zip "WP-Polls 2.20 For WordPress 2.1.x, 2.2.x And 2.3.x") -* [WP-Polls 2.13 For WordPress 2.0.x](http://downloads.wordpress.org/plugin/wp-polls.2.13.zip "WP-Polls 2.13 For WordPress 2.0.x") -* [WP-Polls 2.02a For WordPress 1.5.2](http://downloads.wordpress.org/plugin/wp-polls.2.02a.zip "WP-Polls 2.02a For WordPress 1.5.2") - -= Development = -* [http://dev.wp-plugins.org/browser/wp-polls/](http://dev.wp-plugins.org/browser/wp-polls/ "http://dev.wp-plugins.org/browser/wp-polls/") - -= Translations = -* [http://dev.wp-plugins.org/browser/wp-polls/i18n/](http://dev.wp-plugins.org/browser/wp-polls/i18n/ "http://dev.wp-plugins.org/browser/wp-polls/i18n/") - -= Support Forums = -* [http://forums.lesterchan.net/index.php?board=15.0](http://forums.lesterchan.net/index.php?board=15.0 "http://forums.lesterchan.net/index.php?board=15.0") - -= Credits = -* __ngetext() by [Anna Ozeritskaya](http://hweia.ru/ "Anna Ozeritskaya") -* Right To Left Language Support by [Kambiz R. Khojasteh](http://persian-programming.com/ "Kambiz R. Khojasteh") - -= Donations = -* I spent most of my free time creating, updating, maintaining and supporting these plugins, if you really love my plugins and could spare me a couple of bucks, I will really appericiate it. If not feel free to use it without any obligations. - -== Changelog == - -= Version 2.64 = -* NEW: Add in various filters in the plugin. Props Machiel. -* FIXED: Deveral undefined variable / undefined index notices. Props Machiel. - -= Version 2.63 (21-05-2012) = -* Move AJAX Request to wp-admin/admin-ajax.php -* Added nonce To AJAX Calls -* FIXED: PHP Notices/add_options() Deprecated Arguments ([Dewey Bushaw](http://www.parapxl.com/ "Dewey Bushaw")) - -= Version 2.62 (31-08-2011) = -* FIXED: Escaped Hostname. Thanks to Renaud Feil ([Renaud Feil](http://www.stratsec.net "Renaud Feil")) -* FIXED: Ensure Poll ID In Shortcode Is An Integer. Thanks to Renaud Feil ([Renaud Feil](http://www.stratsec.net "Renaud Feil")) - -= Version 2.61 (14-02-2011) = -* FIXED: XSS Vulnerability. Thanks to Dweeks, Leon Juranic and Chad Lavoie of the Swiftwill Security Team Inc ([www.swiftwill.com](http://www.swiftwill.com "www.swiftwill.com")) - -= Version 2.60 (01-12-2009) = -* NEW: Uses WordPress nonce Throughout -* NEW: Display 2,000 Records In Poll Logs Instead Of 100 - -= Version 2.50 (01-06-2009) = -* NEW: Works For WordPress 2.8 Only -* NEW: Javascript Now Placed At The Footer -* NEW: Uses jQuery Instead Of tw-sack -* NEW: Minified Javascript Instead Of Packed Javascript -* NEW: Renamed polls-admin-js-packed.js To polls-admin-js.js -* NEW: Renamed polls-admin-js.js To polls-admin-js.dev.js -* NEW: Renamed polls-js-packed.js To polls-js.js -* NEW: Renamed polls-js.js To polls-js.dev.js -* NEW: Translate Javascript Variables Using wp_localize_script() -* NEW: Add "Add Poll" To WordPress Favourite Actions -* NEW: Minified editor_plugin.js And Added Non-Minified editor_plugin.dev.js -* NEW: Able To Remove Individual Answers When Adding Or Editing A Poll -* NEW: Use _n() Instead Of __ngettext() And _n_noop() Instead Of __ngettext_noop() -* NEW: Uses New Widget Class From WordPress -* NEW: Merge Widget Code To wp-polls.php And Remove wp-polls-widget.php -* FIXED: Uses $_SERVER['PHP_SELF'] With plugin_basename(__FILE__) Instead Of Just $_SERVER['REQUEST_URI'] -* FIXED: Ensure That Percentage Always Add Up To 100% -* FIXED: More Efficient WP-Polls Archive -* FIXED: Logged By Username Now Shows Poll Results To Users Who Did Not Login - -= Version 2.40 (12-12-2008) = -* NEW: Works For WordPress 2.7 Only -* NEW: Load Admin JS And CSS Only In WP-Polls Admin Pages -* NEW: Added polls-admin-css.css For WP-Polls Admin CSS Styles -* NEW: Right To Left Language Support by Kambiz R. Khojasteh -* NEW: Added "polls-css-rtl.css" by Kambiz R. Khojasteh -* NEW: Applied Output Of polls_archive() To "polls_archive" Filter by Kambiz R. Khojasteh -* NEW: Added Call To polls_textdomain() In create_poll_table() and vote_poll() functions by Kambiz R. Khojasteh -* NEW: Uses wp_register_style(), wp_print_styles(), plugins_url() And site_url() -* NEW: [poll id="-2"] or <?php get_poll(-2); ?> Will Randomize The Poll -* FIXED: SSL Support -* FIXED: Moved Call To update_pollbar() From onblur To onclick Event. It Was Showing The Last Selection Instead Of Current One by Kambiz R. Khojasteh - -= Version 2.31 (16-07-2008) = -* NEW: Works For WordPress 2.6 -* NEW: Better Translation Using __ngetext() by Anna Ozeritskaya -* FIXED: MYSQL Charset Issue Should Be Solved - -= Version 2.30 (01-06-2008) = -* NEW: Works For WordPress 2.5 Only -* NEW: Added Paging Header And Footer Template For Polls Archive Page -* NEW: Uses WP-PageNavi Style Paging For Polls Archive Page -* NEW: WP-Polls Will Load 'polls-css.css' Inside Your Theme Directory If It Exists. If Not, It Will Just Load The Default 'polls-css.css' By WP-Polls -* NEW: Uses Shortcode API -* NEW: When Inserting Poll Into Post, It is Now [poll id="1"], Where 1 Is Your Poll ID -* NEW: When User Does Not Have Permission To Vote, The Voting Form Is Now Disabled Instead Of Showing Poll's Result -* NEW: Added A New Action Called "Display Disabled Poll's Voting Form" To Action Taken When A Poll Is Closed -* NEW: Updated WP-Polls TinyMCE Plugin To Work With TinyMCE 3.0 -* NEW: Add Time Expiry For Cookie/Log -* NEW: Removed polls-usage.php -* NEW: Removed "Fade Anything Technique" In Polls Admin -* NEW: Uses /wp-polls/ Folder Instead Of /polls/ -* NEW: Uses wp-polls.php Instead Of polls.php -* NEW: Uses wp-polls-widget.php Instead Of polls-widget.php -* NEW: Use number_format_i18n() Instead -* NEW: Renamed polls-admin-js.php To polls-admin-js.js and Move The Dynamic Javascript Variables To The PHP Pages -* NEW: Renamed polls-js.php To polls-js.js and Move The Dynamic Javascript Variables To The PHP Pages -* NEW: Uses polls-js-packed.js And polls-admin-js-packed.js -* FIXED: Unable To Delete Poll Or Poll Answers If There Is Quotes Within The Poll Or Poll Answer -* FIXED: number_format() Not Used In Polls Archive -* FIXED: Unable To Schedule Future Poll If The Year Is Different From Current Year -* FIXED: TinyMCE Tool Tip For Insert Poll Not Translated -* FIXED: Content-Type Not Being Sent Back When AJAX Return Results - -= Version 2.21 (01-10-2007) = -* NEW: Works For WordPress 2.3 Only -* NEW: Added Quick Tag For Poll To Visual (TinyMCE) / Code Editor -* NEW: New CSS Style For WP-Polls Archive (.wp-polls-archive) -* NEW: Uses WP-Stats Filter To Add Stats Into WP-Stats Page -* NEW: Ability To Add Polls To Excerpt -* NEW: Added "Random Order" For Sorting Poll's Answers And Poll's Result Answers -* FIXED: Language Problem By Setting Database Table To UTF8 -* FIXED: Some Text Not Translated In Polls Widget -* FIXED: 2 Wrong Options Name In Polls Uninstall -* FIXED: Some Translation Bug in polls-usage.php - -= Version 2.20 (01-06-2007) = -* NEW: Poll Archive Link, Individual Poll Header And Footer In Poll Archive Template -* NEW: Poll Templates Has Now Its Own Page 'WP-Admin -> Polls -> Poll Templates' -* NEW: Poll Widget Can Now Display Multiple Polls -* NEW: Ability To Allow User To Select More Than 1 Poll Answer -* NEW: Added AJAX Style Option: "Show Loading Image With Text" -* NEW: Added AJAX Style Option: "Show Fading In And Fading Out Of Polls" -* NEW: Major Changes To The Administration Panel For WP-Polls -* NEW: AJAX Added To The Administration Panel For WP-Polls -* NEW: Default Poll's Result Template Will Now Show Number Of Votes Beside The Percentage -* NEW: Term "Total Votes" Changed To "Total Voters" -* NEW: Removed Polls From Feed If The Poll Is Embedded Into The Post Using [poll=ID] -* NEW: Filtering Of Individual Poll Logs -* FIXED: Poll Archive Will Now Show Only Polls Results - -= Version 2.14 (01-02-2007) = -* NEW: Works For WordPress 2.1 Only -* NEW: Renamed polls-js.js to polls-js.php To Enable PHP Parsing -* NEW: Ability To Make A Poll Expire -* NEW: Ability To Make A Future Poll -* NEW: Future Poll Will Automatically Open When The Poll's Date Is Reached -* NEW: Expired Poll Will Automatically Closed When The Poll's Date Is Reached -* NEW: Ablity To Choose What To Do When The Poll Is Closed (Display Result, Remove Poll From Sidebar) -* FIXED: Future Dated Polls Will Not Appear In The Post/Sidebar/Polls Archive - -= Version 2.13 (02-01-2007) = -* NEW: polls.php Now Handles The AJAX Processing Instead Of index.php -* NEW: Able To Modify The Style Of Poll Results Bar in 'Polls -> Poll Option' -* NEW: Usage Instructions Is Also Included Within The Plugin Itself -* NEW: Uninstaller Done By Philippe Corbes -* NEW: Localization Done By Ravan -* NEW: Ability To Add HTML Into Poll Question and Answers -* FIXED: AJAX Not Working On Servers Running On PHP CGI -* FIXED: Added Some Default Styles To polls-css.css To Ensure That WP-Polls Does Not Break -* FIXED: Other Languages Not Appearing Properly -* FIXED: Poll IP Logs Of Deleted Poll's Answer Did Not Get Deleted -* FIXED: There Is An Error In Voting If There Is Only 1 Poll's Answer - -= Version 2.12 (01-10-2006) = -* NEW: Polls Archive Is Now Embedded Into A Page, And Hence No More Integrating Of Polls Archive -* NEW: WP-Polls Is Now Using DIV To Display The Poll's Results Instead Of The Image Bar -* NEW: Added Widget Title Option To WP-Polls Widget -* NEW: Ability To Logged By UserName -* NEW: Added CSS Class 'wp-polls-image' To All IMG Tags -* FIXED: If Site URL Doesn't Match WP Option's Site URL, WP-Polls Will Not Work - -= Version 2.11 (08-06-2006) = -* NEW: You Can Now Place The Poll On The Sidebar As A Widget -* NEW: Moved wp-polls.php To wp-content/plugins/polls/ Folder -* FIXED: AJAX Not Working In Opera Browser -* FIXED: Poll Not Working On Physical Pages That Is Integrated Into WordPress - -= Version 2.1 (01-06-2006) = -* NEW: Poll Is Now Using AJAX -* NEW: Ability To Close/Open Poll -* NEW: Added Poll Option For Logging Method -* NEW: Added Poll Option For Who Can Vote -* NEW: Added Poll Results Footer Template Variable (Used When User Click "View Results") -* NEW: Added The Ability To Delete All Poll Logs Or Logs From A Specific Poll -* NEW: Poll Administration Panel And The Code That WP-Polls Generated Is XHTML 1.0 Transitional - -= Version 2.06b (26-04-2006) = -* FIXED: Bug In vote_poll(); - -= Version 2.06a (02-04-2006) = -* FIXED: Random Poll Not Working Correctly - -= Version 2.06 (01-04-2006) = -* NEW: Poll Bar Is Slightly Nicer -* NEW: Got Rid Of Tables, Now Using List -* NEW: Added In Most Voted And Least Voted Answer/Votes/Percentage For Individual Poll As Template Variables -* NEW: Display Random Poll Option Under Poll -> Poll Options -> Current Poll -* FIXED: Totally Removed Tables In wp-polls.php - -= Version 2.05 (01-03-2006) = -* NEW: Improved On 'manage_polls' Capabilities -* NEW: Neater Structure -* NEW: No More Install/Upgrade File, It Will Install/Upgrade When You Activate The Plugin -* NEW: Added Poll Stats Function - -= Version 2.04 (01-02-2006) = -* NEW: Added 'manage_polls' Capabilities To Administrator Role -* NEW: [poll=POLL_ID] Tag To Insert Poll Into A Post -* NEW: Ability To Edit Poll's Timestamp -* NEW: Ability To Edit Individual Poll's Answer Votes -* NEW: %POLL_RESULT_URL% To Display Poll's Result URL -* FIXED: Cannot Sent Header Error - -= Version 2.03 (01-01-2006) = -* NEW: Compatible With WordPress 2.0 Only -* NEW: Poll Administration Menu Added Automatically Upon Activating The Plugin -* NEW: Removed Add Poll Link From The Administration Menu -* NEW: GPL License Added -* NEW: Page Title Added To wp-polls.php - -= Version 2.02a (17-11-2005) = -* FIXED: poll-install.php And poll-upgrade.php will Now Be Installed/Upgraded To 2.02 Instead Of 2.01 - -= Version 2.02 (05-11-2005) = -* FIXED: Showing 0 Vote On Poll Edit Page -* FIXED: Null Vote Being Counted As A Vote -* FIXED: Auto Loading Of Poll Option: Polls Per Page In Poll Archive Page Is Now "No" -* NEW: Host Column In Poll IP Table To Prevent Network Lagging When Resolving IP -* NEW: New Poll Error Template - -= Version 2.01 (25-10-2005) = -* FIXED: Upgrade Script To Insert Lastest Poll ID Of User's Current Polls, Instead Of Poll ID 1 -* FIXED: Replace All <?### With <?php -* FIXED: Added addalshes() To $pollip_user -* FIXED: Better Localization Support (80% Done, Will Leave It In The Mean Time) - -= Version 2.0 (20-10-2005) = -* NEW: IP Logging -* NEW: Poll Options: Sorting Of Answers In Voting Form -* NEW: Poll Options: Sorting Of Answers In Results View -* NEW: Poll Options: Number Of Polls Per Page In Poll Archive -* NEW: Poll Options: Choose Poll To Display On Index Page -* NEW: Poll Options: Able To Disable Poll With Custom Message -* NEW: Poll Options: Poll Templates -* NEW: Display User's Voted Choice -* FIXED: Better Install/Upgrade Script - -== Installation == - -1. Open `wp-content/plugins` Folder -2. Put: `Folder: wp-polls` -3. Activate `WP-Polls` Plugin -4. Go to `WP-Admin -> WP-Polls` - -= General Usage (Without Widget) = -1. Open `wp-content/themes/<YOUR THEME NAME>/sidebar.php` -2. Add: -<code> -<?php if (function_exists('vote_poll') && !in_pollarchive()): ?> - <li> - <h2>Polls</h2> - <ul> - <li><?php get_poll();?></li> - </ul> - <?php display_polls_archive_link(); ?> - </li> -<?php endif; ?> -</code> - -* To show specific poll, use `<?php get_poll(2); ?>` where 2 is your poll id. -* To show random poll, use `<?php get_poll(-2); ?>` -* To embed a specific poll in your post, use `[poll id="2"]` where 2 is your poll id. -* To embed a random poll in your post, use `[poll id="-2"]` -* To embed a specific poll's result in your post, use `[poll id="2" type="result"]` where 2 is your poll id. - -= General Usage (With Widget) = -1. Go to `WP-Admin -> Appearance -> Widgets`. -2. You can add the Polls Widget by clicking on the 'Add' link besides it. -3. After adding, you can configure the Polls Widget by clicking on the 'Edit' link besides it. -4. Click 'Save Changes'. -5. Scroll down for instructions on how to create a Polls Archive. - -== Upgrading == - -1. Deactivate `WP-Polls` Plugin -2. Open `wp-content/plugins` Folder -3. Put/Overwrite: `Folder: wp-polls` -4. Activate `WP-Polls` Plugin -5. Go to `WP-Admin -> Polls -> Polls Templates` and restore all the template variables to `Default` -6. Go to `WP-Admin -> Appearance -> Widgets` and re-add the Poll Widget - -== Upgrade Notice == - -N/A - -== Screenshots == - -1. Admin - All Poll -2. Admin - Manage Polls -3. Admin - Poll Options -4. Admin - Poll Templates -5. Admin - Poll Widget -6. Admin - Uninstall Poll -7. Poll - Single Poll Answer -8. Poll - Mutiple Poll Answers -9. Poll - Results -10. Poll - Archive - -== Frequently Asked Questions == - - -= How To Add A Polls Archive? = -1. Go to `WP-Admin -> Pages -> Add New`. -2. Type any title you like in the post's title area. -3. If you ARE using nice permalinks, after typing the title, WordPress will generate the permalink to the page. You will see an 'Edit' link just beside the permalink. -4. Click 'Edit' and type in `pollsarchive` in the text field and click 'Save'. -5. Type `[page_polls]` in the post's content area. -6. Click 'Publish'. - -* If you ARE NOT using nice permalinks, you need to go to `WP-Admin -> Polls -> Poll Options` and under `Poll Archive -> Polls Archive URL`, you need to fill in the URL to the Polls Archive Page you created above. - -= How Does WP-Polls Load CSS? = -* WP-Polls will load 'polls-css.css' from your theme's directory if it exists. -* If it doesn't exists, it will just load the default 'polls-css.css' that comes with WP-Polls. -* This will allow you to upgrade WP-Polls without worrying about overwriting your polls styles that you have created. - -= Why In Internet Explorer (IE) The poll's Text Appear Jagged? = -* To solve this issue, Open poll-css.css -* Find: `/* background-color: #ffffff; */` -* Replace: `background-color: #ffffff;` (where #ffffff should be your background color for the poll.) - -= How Do I Have Individual Colors For Each Poll's Bar? = -* Courtesy Of [TreedBox.com](http://treedbox.com "TreedBox.com") -* Open poll-css.css -* Add to the end of the file: - -<code> -.wp-polls-ul li:nth-child(01) .pollbar{ background:#8FA0C5} -.wp-polls-ul li:nth-child(02) .pollbar{ background:#FF8} -.wp-polls-ul li:nth-child(03) .pollbar{ background:#ff8a3b} -.wp-polls-ul li:nth-child(04) .pollbar{ background:#a61e2a} -.wp-polls-ul li:nth-child(05) .pollbar{ background:#4ebbff} -.wp-polls-ul li:nth-child(06) .pollbar{ background:#fbca54} -.wp-polls-ul li:nth-child(07) .pollbar{ background:#aad34f} -.wp-polls-ul li:nth-child(08) .pollbar{ background:#66cc9a} -.wp-polls-ul li:nth-child(09) .pollbar{ background:#98CBCB} -.wp-polls-ul li:nth-child(10) .pollbar{ background:#a67c52} -.wp-polls-ul li .pollbar{-webkit-transition: background 0.7s ease-in-out} -.wp-polls-ul li .pollbar:hover{background:#F00} -</code> - -= Polls Stats (Outside WP Loop) = - -= To Display Total Polls = -* Use: -<code> -<?php if (function_exists('get_pollquestions')): ?> - <?php get_pollquestions(); ?> -<?php endif; ?> -</code> - -= To Display Total Poll Answers = -* Use: -<code> -<?php if (function_exists('get_pollanswers')): ?> - <?php get_pollanswers(); ?> -<?php endif; ?> -</code> - -= To Display Total Poll Votes = -* Use: -<code> -<?php if (function_exists('get_pollvotes')): ?> - <?php get_pollvotes(); ?> -<?php endif; ?> -</code> - -= To Display Total Poll Voters = -* Use: -<code> -<?php if (function_exists('get_pollvoters')): ?> - <?php get_pollvoters(); ?> -<?php endif; ?> -</code> diff --git a/spec/samples/common/models/wp_item/versionable/wp_user_frontend.txt b/spec/samples/common/models/wp_item/versionable/wp_user_frontend.txt deleted file mode 100644 index fe6d9e83..00000000 --- a/spec/samples/common/models/wp_item/versionable/wp_user_frontend.txt +++ /dev/null @@ -1,235 +0,0 @@ -=== WP User Frontend === -Contributors: tareq1988 -Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=tareq%40wedevs%2ecom&lc=US&item_name=WP%20User%20Frontend&item_number=Tareq%27s%20Planet¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted -Tags: frontend, post, edit, dashboard, restrict, content submission, guest post, guest, dashboard, registration, profile, anonymous post, gravity, gravity forms, formidable -Requires at least: 3.3 -Tested up to: 3.5.2 -Stable tag: trunk - -Create, update, delete posts and edit profile from wordpress frontend. - -== Description == - -Gives ability to the user to create new post, edit post, edit profile from site frontend. -So users doesn't need to enter the admin panel. Everything they need to do can be done from -the frontend. - -= Features: = - -So here is my plugin that solves your problem. This features of this plugin are follows: - -* User can create a new post and edit from frontend -* They can view their page in the custom dashboard -* Users can edit their profile -* Administrator can restrict any user level to access the wordpress backend (/wp-admin) -* New posts status, submitted by users are configurable via admin panel. i.e. Published, Draft, Pending -* Admin can configure to receive notification mail when the users creates a new post. -* Configurable options if the user can edit or delete their posts. -* Users can upload attachments from the frontend -* Post featured image can be set -* Admins can manage their users from frontend -* Pay per post or subscription on posting is possible - -= WP User Frontend PRO = - -The <a href="http://wedevs.com/plugin/wp-user-frontend-pro">premium version</a> of WP User Frontend comes with tons of features: - -[youtube http://www.youtube.com/watch?v=C0sInxx49Vg] - -* Unlimited post type form creation -* Drag-n-drop form builder -* Custom taxonomy support -* 13 variations of custom fields -* Guest post support -* Custom Redirection -* Image upload on post content area -* Post status selection on new post and edited post separately -* New or edit post notification -* Custom fields are generated also in admin area -* <strong>Profile form builder</strong> -* Different profile edit forms for different user roles -* Drag-n-Drop profile form builder -* Profile fields are generated on backend too -* Avatar Upload -* Frontend profile edit -* <strong>Registration form</strong> builder -* Captcha Support -* Theme My Login compatible -* Much more... - -<a href="http://wedevs.com/plugin/wp-user-frontend-pro">Try out the awesome Pro version</a> of bunch of features - -= Translation = - -* Italian translation by Gabriele Lamberti - - -== Installation == - -This section describes how to install the plugin and get it working. - -1. Create a new Page “New Post” and insert shorcode `[wpuf_addpost]`. - For a custom post type **event**, use it like `[wpuf_addpost post_type="event"]` -1. Create a new Page “Edit” for editing posts and insert shorcode `[wpuf_edit]` -1. Create a new Page “Profile” for editing profile and insert shorcode `[wpuf_editprofile]` -1. Create a new Page “Dashboard” and insert shorcode `[wpuf_dashboard]` - To list custom post type **event**, use it like `[wpuf_dashboard post_type="event"]` -1. Set the *Edit Page* option from *Others* tab on settings page. -1. To show the subscription info, insert the shortcdoe `[wpuf_sub_info]` -1. To show the subscription packs, insert the shortcode `[wpuf_sub_pack]` -1. For subscription payment page, set the *Payment Page* from *Payments* tab on settings page. -1. To edit users, insert the shortcode `[wpuf-edit-users]` - - -== Screenshots == -1. Admin panel -2. User Dashboard -3. Add Post -4. Edit Posts -5. Edit Profile -6. Custom Field Manager -7. Subscription Pack Manager -8. Subscription packs -9. Edit Users - -== Frequently Asked Questions == - -= Can I create new posts from frontend = - -Yes - -= Can I Edit my posts from frontend = - -Yes - -= Can I delete my posts from frontend = - -Yes - -= Can I upload photo/image/video = -Yes - -= I am having problem with uploading files = -Please check if you've specified the max upload size on setting - -= Why "Edit Post" page shows "invalid post id"?= -This page is for the purpose of editing posts. You shouldn't access this page directly. -First you need to go to the dashboard, then when you click "edit", you'll be -redirected to the edit page with that post id. Then you'll see the edit post form. - - -== Changelog == - -= version 1.2.3 = - -[fix] `has_shortcode()` brought back again by renaming as `wpuf_has_shortcode()` -[fix] all the labels now have a default text - -= version 1.2.2 = - -[fix] shortcode error fix for edit users -[fix] plugin css/js url -[fix] removed has_shortcode() call - -= version 1.2.1 = - -[fix] Performance problem with wp_list_users() - -= version 1.2 = - -* [fix] Subscription post publish -* [fix] Post delete fix in dashboard -* [fix] Silverlight in IE upload error -* [fix] Category checklist bug fix -* [new] Checkbox field in custom field - -= version 1.1 = - -* warning for multisite fix -* allow category bug fix -* fix ajaxurl in ajaxified category -* custom post type dropdown fix in admin -* post date bug fix -* category dropdown fix - -= version 1.0 = - -* Admin panel converted to settings API -* Ajax featured Image uploader added (using plupload) -* Ajax attachment uploader added (using plupload) -* Rich/full/normal text editor mode -* Editor button fix on twentyelven theme -* Massive Code rewrite and cleanup -* Dashboard replaced with WordPress loop -* Output buffering added for header already sent warning -* Redirect user on deleting a post -* Category checklist added -* Post publish date fix and post expirator changed from hours to day -* Subscription and payment rewrite. Extra payment gateways can be added as plugin -* Other payment currency added - -= version 0.7 = - -* admin ui improved -* updated new post notification mail template -* custom fields and attachment show/hide in posts -* post edit link override option -* ajax "posting..." changed -* attachment fields restriction in edit page -* localized ajaxurl and posting message -* improved action hooks and filter hooks - -= version 0.6 = ---------------- - -* fixed error on attachment delete -* added styles on dashboard too -* fixed custom field default dropdown -* fixed output buffering for add_post/edit_post/dashboard/profile pages -* admin panel scripts are added wp_enqueue_script instead of echo -* fixed admin panel block logic -* filter hook added on edit post for post args - -= version 0.5 = - -* filters on add posting page for blocking the post capa -* subscription pack id added on user meta upon purchase -* filters on add posting page for blocking the post capa -* option for force pack purchase on add post. dropdown p -* subscription info on profile edit page -* post direction fix after payment -* filter added on form builder - - -= version 0.4 = - -* missing custom meta field added on edit post form -* jQuery validation added on edit post form - -= version 0.3 = - -* rich/plain text on/off fixed -* ajax chained category added on add post form -* missing action added on edit post form -* stripslashes on admin/frontend meta field -* 404 error fix on add post - -= version 0.2 = - -* Admin settings page has been improved -* Header already sent warning messages has been fixed -* Now you can add custom post meta from the settings page -* A new pay per post and subscription based posting options has been introduced (Only paypal is supported now) -* You can upload attachment with post -* WYSIWYG editor has been added -* You can add and manage your users from frontend now (only having the capability to edit_users ) -* Some action and filters has been added for developers to add their custom form elements and validation -* Pagination added in post dashboard -* You can use the form to accept "custom post type" posts. e.g: [wpuf_addpost post_type="event"]. It also applies for showing post on dashboard like "[wpuf_dashboard post_type="event"]" -* Changing the form labels of the add post form is now possible from admin panel. -* The edit post page setting is changed from URL to page select dropdown. -* You can lock certain users from posting from their edit profile page. - -== Upgrade Notice == - -Nothing to say diff --git a/spec/samples/common/models/wp_item/vulnerable/empty.json b/spec/samples/common/models/wp_item/vulnerable/empty.json deleted file mode 100644 index 9e26dfee..00000000 --- a/spec/samples/common/models/wp_item/vulnerable/empty.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/spec/samples/common/models/wp_item/vulnerable/items_vulns.json b/spec/samples/common/models/wp_item/vulnerable/items_vulns.json deleted file mode 100644 index b221ffc9..00000000 --- a/spec/samples/common/models/wp_item/vulnerable/items_vulns.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "not-this-one": { - "vulnerabilities":[ - { - "id":2989, - "title":"Administrator-exploitable blind SQLi in WordPress 1.0 - 3.8.1", - "references": { - "url": ["https://security.dxw.com/advisories/sqli-in-wordpress-3-6-1/" ,"http://www.example.com"] - }, - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:43:41.000Z" - } - ] - }, - "neo": { - "vulnerabilities":[ - { - "id":2993, - "title":"I'm the one", - "references": { - "url": ["Ref 1", "Ref 2"], - "osvdb": ["osvdb"], - "cve": ["2011-001"], - "secunia": ["secunia"], - "metasploit": ["exploit/ex1"], - "exploitdb": ["exploitdb"] - }, - "type":"XSS", - "fixed_in":"", - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - } - ] - } -} diff --git a/spec/samples/common/models/wp_plugin/vulnerable/plugins.json b/spec/samples/common/models/wp_plugin/vulnerable/plugins.json deleted file mode 100644 index 7498bd34..00000000 --- a/spec/samples/common/models/wp_plugin/vulnerable/plugins.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "mr-smith": { - "vulnerabilities":[ - { - "id":2993, - "title":"I should not appear in the results", - "references": { - "url": ["Ref 1","Ref 2"], - "osvdb": ["osvdb"], - "cve": ["2011-001"], - "secunia": ["secunia"], - "metasploit": ["exploit/ex1"], - "exploitdb": ["exploitdb"] - }, - "type":"XSS", - "fixed_in":"", - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - }, - { - "id":2989, - "title":"Neither do I", - "references": { - "url": ["Ref 1" ,"Ref 2"], - "osvdb": ["osvdb"], - "cve": ["2011-001"], - "secunia": ["secunia"], - "metasploit": ["exploit/ex1"], - "exploitdb": ["exploitdb"] - }, - "type":"XSS", - "fixed_in":"", - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - } - ] - }, - "white-rabbit": { - "vulnerabilities": [ - { - "id":2993, - "title":"Follow me!", - "references": { - "url": ["Ref 1", "Ref 2"], - "osvdb": ["osvdb"], - "cve": ["2011-001"], - "secunia": ["secunia"], - "metasploit": ["exploit/ex1"], - "exploitdb": ["exploitdb"] - }, - "type":"REDIRECT", - "fixed_in":"", - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - } - ] - } -} diff --git a/spec/samples/common/models/wp_theme/findable/css_link/comments.html b/spec/samples/common/models/wp_theme/findable/css_link/comments.html deleted file mode 100644 index 22dcb959..00000000 --- a/spec/samples/common/models/wp_theme/findable/css_link/comments.html +++ /dev/null @@ -1,11 +0,0 @@ -<script type='text/javascript' src="http://wp.lab/wp-content/themes/debug/scripts/debug.js"></script> - -<!-- W3 Total Cache: Minify debug info: -Engine: apc -Theme: 88e17 -Template: page-home - -Replaced CSS files: -1. wp-content/themes/debug/style.css -2. wp-content/themes/debug/css/responsive.css ---> diff --git a/spec/samples/common/models/wp_theme/findable/css_link/inline_link_tag.html b/spec/samples/common/models/wp_theme/findable/css_link/inline_link_tag.html deleted file mode 100644 index 5400d601..00000000 --- a/spec/samples/common/models/wp_theme/findable/css_link/inline_link_tag.html +++ /dev/null @@ -1 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="de-DE"><head profile="http://gmpg.org/xfn/11"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>WP diff --git a/spec/samples/common/models/wp_theme/findable/css_link/relative_urls.html b/spec/samples/common/models/wp_theme/findable/css_link/relative_urls.html deleted file mode 100644 index da4b65bf..00000000 --- a/spec/samples/common/models/wp_theme/findable/css_link/relative_urls.html +++ /dev/null @@ -1 +0,0 @@ -Test diff --git a/spec/samples/common/models/wp_theme/findable/css_link/relative_urls_missing_slash.html b/spec/samples/common/models/wp_theme/findable/css_link/relative_urls_missing_slash.html deleted file mode 100644 index e3de22a0..00000000 --- a/spec/samples/common/models/wp_theme/findable/css_link/relative_urls_missing_slash.html +++ /dev/null @@ -1 +0,0 @@ -Test diff --git a/spec/samples/common/models/wp_theme/findable/css_link/theme-name-with-spaces.html b/spec/samples/common/models/wp_theme/findable/css_link/theme-name-with-spaces.html deleted file mode 100644 index f8d6b231..00000000 --- a/spec/samples/common/models/wp_theme/findable/css_link/theme-name-with-spaces.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - -wordpress-3.2.1 | Just another WordPress site - - - - - - - - - - - - - diff --git a/spec/samples/common/models/wp_theme/findable/css_link/yootheme.html b/spec/samples/common/models/wp_theme/findable/css_link/yootheme.html deleted file mode 100644 index 03a90db7..00000000 --- a/spec/samples/common/models/wp_theme/findable/css_link/yootheme.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - -XXXXX - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spec/samples/common/models/wp_theme/findable/wooframework/editorial-1.3.5.html b/spec/samples/common/models/wp_theme/findable/wooframework/editorial-1.3.5.html deleted file mode 100644 index bcd07ded..00000000 --- a/spec/samples/common/models/wp_theme/findable/wooframework/editorial-1.3.5.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - Target site - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spec/samples/common/models/wp_theme/findable/wooframework/merchant-no-version.html b/spec/samples/common/models/wp_theme/findable/wooframework/merchant-no-version.html deleted file mode 100644 index 82202969..00000000 --- a/spec/samples/common/models/wp_theme/findable/wooframework/merchant-no-version.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - Target site - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spec/samples/common/models/wp_theme/versionable/bueno-1.5.1.css b/spec/samples/common/models/wp_theme/versionable/bueno-1.5.1.css deleted file mode 100644 index 4b608fa4..00000000 --- a/spec/samples/common/models/wp_theme/versionable/bueno-1.5.1.css +++ /dev/null @@ -1,16 +0,0 @@ -/* Theme Name: Bueno Version: 1.5.1 Description: Designed by WooThemes -Author: WooThemes Author URI: http://www.woothemes.com Copyright: (c) 2009 WooThemes. -License: GNU/GPL Version 2 or later. http://www.gnu.org/licenses/gpl.html */ /* -WARNING! DO NOT EDIT THIS FILE! To make it easy to update your theme, you should -not edit the styles in this file. Instead use the custom.css file to add your -styles. You can copy a style from this file and paste it in custom.css and it -will override the style in this file. You have been warned! :) */ /* Default styles -*/ @import "css/reset.css"; /*------------------------------------------------------------------------------------------- -INDEX: 1. SETUP -1.1 Defaults -1.2 Hyperlinks 2. SITE STRUCTURE & APPEARANCE -2.1 -Containers & Columns -2.2 Navigation -2.2.1 Drop-down menus -2.3 Header -2.4 Content --2.5 Sidebar -2.6 Extended Footer -2.7 Footer 3. POSTS -3.1 Typographic Elements --3.2 Images -3.3 Pagination / WP-Pagenavi 4. WIDGETS -4.1 Generic Widgets -4.2 -Specific Widgets -4.3 Extended Footer Widgets 5. COMMENTS -5.1 Comments -5.2 Pingbacks -/ Trackbacks -5.3 Comments Form -5.4 Gravity forms -------------------------------------------------------------------------------------------*/ -/*-------------------------------------------------------------------------------------------*/ -/* 1. SETUP */ /*-------------------------------------------------------------------------------------------*/ diff --git a/spec/samples/common/models/wp_theme/versionable/firefart.net.css b/spec/samples/common/models/wp_theme/versionable/firefart.net.css deleted file mode 100644 index 5cd8aa0f..00000000 --- a/spec/samples/common/models/wp_theme/versionable/firefart.net.css +++ /dev/null @@ -1,11 +0,0 @@ -/* - Theme Name: firefart.net - Theme URI: http://www.firefart.net/ - Description: firefart.net Theme - Author: Christian Mehlmauer - Author URI: http://www.firefart.net% - Template: twentytwelve - Version: 1.0.0 -*/ - -@import url("../twentytwelve/style.css"); diff --git a/spec/samples/common/models/wp_theme/versionable/twentyeleven-1.3.css b/spec/samples/common/models/wp_theme/versionable/twentyeleven-1.3.css deleted file mode 100644 index 03dd3212..00000000 --- a/spec/samples/common/models/wp_theme/versionable/twentyeleven-1.3.css +++ /dev/null @@ -1,2679 +0,0 @@ -/* -Theme Name: Twenty Eleven -Theme URI: http://wordpress.org/extend/themes/twentyeleven -Author: the WordPress team -Author URI: http://wordpress.org/ -Description: The 2011 theme for WordPress is sophisticated, lightweight, and adaptable. Make it yours with a custom menu, header image, and background -- then go further with available theme options for light or dark color scheme, custom link colors, and three layout choices. Twenty Eleven comes equipped with a Showcase page template that transforms your front page into a showcase to show off your best content, widget support galore (sidebar, three footer areas, and a Showcase page widget area), and a custom "Ephemera" widget to display your Aside, Link, Quote, or Status posts. Included are styles for print and for the admin editor, support for featured images (as custom header images on posts and pages and as large images on featured "sticky" posts), and special styles for six different post formats. -Version: 1.3" -License: GNU General Public License -License URI: license.txt -Tags: dark, light, white, black, gray, one-column, two-columns, left-sidebar, right-sidebar, fixed-width, flexible-width, custom-background, custom-colors, custom-header, custom-menu, editor-style, featured-image-header, featured-images, full-width-template, microformats, post-formats, rtl-language-support, sticky-post, theme-options, translation-ready -*/ - -/* =Reset default browser CSS. Based on work by Eric Meyer: http://meyerweb.com/eric/tools/css/reset/index.html --------------------------------------------------------------- */ - -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, font, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td { - border: 0; - font-family: inherit; - font-size: 100%; - font-style: inherit; - font-weight: inherit; - margin: 0; - outline: 0; - padding: 0; - vertical-align: baseline; -} -:focus {/* remember to define focus styles! */ - outline: 0; -} -body { - background: #fff; - line-height: 1; -} -ol, ul { - list-style: none; -} -table {/* tables still need 'cellspacing="0"' in the markup */ - border-collapse: separate; - border-spacing: 0; -} -caption, th, td { - font-weight: normal; - text-align: left; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ""; -} -blockquote, q { - quotes: "" ""; -} -a img { - border: 0; -} -article, aside, details, figcaption, figure, -footer, header, hgroup, menu, nav, section { - display: block; -} - - -/* =Structure ------------------------------------------------ */ - -body { - padding: 0 2em; -} -#page { - margin: 2em auto; - max-width: 1000px; -} -#branding hgroup { - margin: 0 7.6%; -} -#access div { - margin: 0 7.6%; -} -#primary { - float: left; - margin: 0 -26.4% 0 0; - width: 100%; -} -#content { - margin: 0 34% 0 7.6%; - width: 58.4%; -} -#secondary { - float: right; - margin-right: 7.6%; - width: 18.8%; -} - -/* Singular */ -.singular #primary { - margin: 0; -} -.singular #content, -.left-sidebar.singular #content { - margin: 0 7.6%; - position: relative; - width: auto; -} -.singular .entry-header, -.singular .entry-content, -.singular footer.entry-meta, -.singular #comments-title { - margin: 0 auto; - width: 68.9%; -} - -/* Attachments */ -.singular .image-attachment .entry-content { - margin: 0 auto; - width: auto; -} -.singular .image-attachment .entry-description { - margin: 0 auto; - width: 68.9%; -} - -/* Showcase */ -.page-template-showcase-php #primary, -.left-sidebar.page-template-showcase-php #primary { - margin: 0; -} -.page-template-showcase-php #content, -.left-sidebar.page-template-showcase-php #content { - margin: 0 7.6%; - width: auto; -} -.page-template-showcase-php section.recent-posts { - float: right; - margin: 0 0 0 31%; - width: 69%; -} -.page-template-showcase-php #main .widget-area { - float: left; - margin: 0 -22.15% 0 0; - width: 22.15%; -} - -/* error404 */ -.error404 #primary { - float: none; - margin: 0; -} -.error404 #primary #content { - margin: 0 7.6%; - width: auto; -} - -/* Alignment */ -.alignleft { - display: inline; - float: left; - margin-right: 1.625em; -} -.alignright { - display: inline; - float: right; - margin-left: 1.625em; -} -.aligncenter { - clear: both; - display: block; - margin-left: auto; - margin-right: auto; -} - -/* Right Content */ -.left-sidebar #primary { - float: right; - margin: 0 0 0 -26.4%; - width: 100%; -} -.left-sidebar #content { - margin: 0 7.6% 0 34%; - width: 58.4%; -} -.left-sidebar #secondary { - float: left; - margin-left: 7.6%; - margin-right: 0; - width: 18.8%; -} - -/* One column */ -.one-column #page { - max-width: 690px; -} -.one-column #content { - margin: 0 7.6%; - width: auto; -} -.one-column #nav-below { - border-bottom: 1px solid #ddd; - margin-bottom: 1.625em; -} -.one-column #secondary { - float: none; - margin: 0 7.6%; - width: auto; -} -/* Simplify the showcase template */ -.one-column .page-template-showcase-php section.recent-posts { - float: none; - margin: 0; - width: 100%; -} -.one-column .page-template-showcase-php #main .widget-area { - float: none; - margin: 0; - width: auto; -} -.one-column .page-template-showcase-php .other-recent-posts { - border-bottom: 1px solid #ddd; -} -/* Simplify the showcase template when small feature */ -.one-column section.featured-post .attachment-small-feature { - border: none; - display: block; - height: auto; - max-width: 60%; - position: static; -} -.one-column article.feature-image.small { - margin: 0 0 1.625em; - padding: 0; -} -.one-column article.feature-image.small .entry-title { - font-size: 20px; - line-height: 1.3em; -} -.one-column article.feature-image.small .entry-summary { - height: 150px; - overflow: hidden; - padding: 0; - text-overflow: ellipsis; -} -.one-column article.feature-image.small .entry-summary a { - left: -9%; -} -/* Remove the margin on singular articles */ -.one-column.singular .entry-header, -.one-column.singular .entry-content, -.one-column.singular footer.entry-meta, -.one-column.singular #comments-title { - width: 100%; -} -/* Simplify the pullquotes and pull styles */ -.one-column.singular blockquote.pull { - margin: 0 0 1.625em; -} -.one-column.singular .pull.alignleft { - margin: 0 1.625em 0 0; -} -.one-column.singular .pull.alignright { - margin: 0 0 0 1.625em; -} -.one-column.singular .entry-meta .edit-link a { - position: absolute; - left: 0; - top: 40px; -} -.one-column.singular #author-info { - margin: 2.2em -8.8% 0; - padding: 20px 8.8%; -} -/* Make sure we have room for our comment avatars */ -.one-column .commentlist > li.comment { - margin-left: 102px; - width: auto; -} -/* Make sure the logo and search form don't collide */ -.one-column #branding #searchform { - right: 40px; - top: 4em; -} -/* Talking avatars take up too much room at this size */ -.one-column .commentlist > li.comment { - margin-left: 0; -} -.one-column .commentlist > li.comment .comment-meta, -.one-column .commentlist > li.comment .comment-content { - margin-right: 85px; -} -.one-column .commentlist .avatar { - background: transparent; - display: block; - padding: 0; - top: 1.625em; - left: auto; - right: 1.625em; -} -.one-column .commentlist .children .avatar { - background: none; - padding: 0; - position: absolute; - top: 2.2em; - left: 2.2em; -} -.one-column #respond { - width: auto; -} - - -/* =Global ------------------------------------------------ */ - -body, input, textarea { - color: #373737; - font: 15px "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: 300; - line-height: 1.625; -} -body { - background: #e2e2e2; -} -#page { - background: #fff; -} - -/* Headings */ -h1,h2,h3,h4,h5,h6 { - clear: both; -} -hr { - background-color: #ccc; - border: 0; - height: 1px; - margin-bottom: 1.625em; -} - -/* Text elements */ -p { - margin-bottom: 1.625em; -} -ul, ol { - margin: 0 0 1.625em 2.5em; -} -ul { - list-style: square; -} -ol { - list-style-type: decimal; -} -ol ol { - list-style: upper-alpha; -} -ol ol ol { - list-style: lower-roman; -} -ol ol ol ol { - list-style: lower-alpha; -} -ul ul, ol ol, ul ol, ol ul { - margin-bottom: 0; -} -dl { - margin: 0 1.625em; -} -dt { - font-weight: bold; -} -dd { - margin-bottom: 1.625em; -} -strong { - font-weight: bold; -} -cite, em, i { - font-style: italic; -} -blockquote { - font-family: Georgia, "Bitstream Charter", serif; - font-style: italic; - font-weight: normal; - margin: 0 3em; -} -blockquote em, blockquote i, blockquote cite { - font-style: normal; -} -blockquote cite { - color: #666; - font: 12px "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: 300; - letter-spacing: 0.05em; - text-transform: uppercase; -} -pre { - background: #f4f4f4; - font: 13px "Courier 10 Pitch", Courier, monospace; - line-height: 1.5; - margin-bottom: 1.625em; - overflow: auto; - padding: 0.75em 1.625em; -} -code, kbd { - font: 13px Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; -} -abbr, acronym, dfn { - border-bottom: 1px dotted #666; - cursor: help; -} -address { - display: block; - margin: 0 0 1.625em; -} -ins { - background: #fff9c0; - text-decoration: none; -} -sup, -sub { - font-size: 10px; - height: 0; - line-height: 1; - position: relative; - vertical-align: baseline; -} -sup { - bottom: 1ex; -} -sub { - top: .5ex; -} - -/* Forms */ -input[type=text], -input[type=password], -textarea { - background: #fafafa; - -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); - box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); - border: 1px solid #ddd; - color: #888; -} -input[type=text]:focus, -textarea:focus { - color: #373737; -} -textarea { - padding-left: 3px; - width: 98%; -} -input[type=text] { - padding: 3px; -} -input#s { - background: url(images/search.png) no-repeat 5px 6px; - -moz-border-radius: 2px; - border-radius: 2px; - font-size: 14px; - height: 22px; - line-height: 1.2em; - padding: 4px 10px 4px 28px; -} -input#searchsubmit { - display: none; -} - -/* Links */ -a { - color: #1982d1; - text-decoration: none; -} -a:focus, -a:active, -a:hover { - text-decoration: underline; -} - -/* Assistive text */ -.assistive-text { - position: absolute !important; - clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ - clip: rect(1px, 1px, 1px, 1px); -} -#access a.assistive-text:active, -#access a.assistive-text:focus { - background: #eee; - border-bottom: 1px solid #ddd; - color: #1982d1; - clip: auto !important; - font-size: 12px; - position: absolute; - text-decoration: underline; - top: 0; - left: 7.6%; -} - - -/* =Header ------------------------------------------------ */ - -#branding { - border-top: 2px solid #bbb; - padding-bottom: 10px; - position: relative; - z-index: 9999; -} -#site-title { - margin-right: 270px; - padding: 3.65625em 0 0; -} -#site-title a { - color: #111; - font-size: 30px; - font-weight: bold; - line-height: 36px; - text-decoration: none; -} -#site-title a:hover, -#site-title a:focus, -#site-title a:active { - color: #1982d1; -} -#site-description { - color: #7a7a7a; - font-size: 14px; - margin: 0 270px 3.65625em 0; -} -#branding img { - height: auto; - margin-bottom: -7px; - width: 100%; -} - - -/* =Menu --------------------------------------------------------------- */ - -#access { - background: #222; /* Show a solid color for older browsers */ - background: -moz-linear-gradient(#252525, #0a0a0a); - background: -o-linear-gradient(#252525, #0a0a0a); - background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#252525), to(#0a0a0a)); /* older webkit syntax */ - background: -webkit-linear-gradient(#252525, #0a0a0a); - -webkit-box-shadow: rgba(0, 0, 0, 0.4) 0px 1px 2px; - -moz-box-shadow: rgba(0, 0, 0, 0.4) 0px 1px 2px; - box-shadow: rgba(0, 0, 0, 0.4) 0px 1px 2px; - clear: both; - display: block; - float: left; - margin: 0 auto 6px; - width: 100%; -} -#access ul { - font-size: 13px; - list-style: none; - margin: 0 0 0 -0.8125em; - padding-left: 0; -} -#access li { - float: left; - position: relative; -} -#access a { - color: #eee; - display: block; - line-height: 3.333em; - padding: 0 1.2125em; - text-decoration: none; -} -#access ul ul { - -moz-box-shadow: 0 3px 3px rgba(0,0,0,0.2); - -webkit-box-shadow: 0 3px 3px rgba(0,0,0,0.2); - box-shadow: 0 3px 3px rgba(0,0,0,0.2); - display: none; - float: left; - margin: 0; - position: absolute; - top: 3.333em; - left: 0; - width: 188px; - z-index: 99999; -} -#access ul ul ul { - left: 100%; - top: 0; -} -#access ul ul a { - background: #f9f9f9; - border-bottom: 1px dotted #ddd; - color: #444; - font-size: 13px; - font-weight: normal; - height: auto; - line-height: 1.4em; - padding: 10px 10px; - width: 168px; -} -#access li:hover > a, -#access ul ul :hover > a, -#access a:focus { - background: #efefef; -} -#access li:hover > a, -#access a:focus { - background: #f9f9f9; /* Show a solid color for older browsers */ - background: -moz-linear-gradient(#f9f9f9, #e5e5e5); - background: -o-linear-gradient(#f9f9f9, #e5e5e5); - background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#f9f9f9), to(#e5e5e5)); /* Older webkit syntax */ - background: -webkit-linear-gradient(#f9f9f9, #e5e5e5); - color: #373737; -} -#access ul li:hover > ul { - display: block; -} -#access .current-menu-item > a, -#access .current-menu-ancestor > a, -#access .current_page_item > a, -#access .current_page_ancestor > a { - font-weight: bold; -} - -/* Search Form */ -#branding #searchform { - position: absolute; - top: 3.8em; - right: 7.6%; - text-align: right; -} -#branding #searchform div { - margin: 0; -} -#branding #s { - float: right; - -webkit-transition-duration: 400ms; - -webkit-transition-property: width, background; - -webkit-transition-timing-function: ease; - -moz-transition-duration: 400ms; - -moz-transition-property: width, background; - -moz-transition-timing-function: ease; - -o-transition-duration: 400ms; - -o-transition-property: width, background; - -o-transition-timing-function: ease; - width: 72px; -} -#branding #s:focus { - background-color: #f9f9f9; - width: 196px; -} -#branding #searchsubmit { - display: none; -} -#branding .only-search #searchform { - top: 5px; - z-index: 1; -} -#branding .only-search #s { - background-color: #666; - border-color: #000; - color: #222; -} -#branding .only-search #s, -#branding .only-search #s:focus { - width: 85%; -} -#branding .only-search #s:focus { - background-color: #bbb; -} -#branding .with-image #searchform { - top: auto; - bottom: -27px; - max-width: 195px; -} -#branding .only-search + #access div { - padding-right: 205px; -} - - -/* =Content ------------------------------------------------ */ - -#main { - clear: both; - padding: 1.625em 0 0; -} -.page-title { - color: #666; - font-size: 10px; - font-weight: 500; - letter-spacing: 0.1em; - line-height: 2.6em; - margin: 0 0 2.6em; - text-transform: uppercase; -} -.page-title a { - font-size: 12px; - font-weight: bold; - letter-spacing: 0; - text-transform: none; -} -.hentry, -.no-results { - border-bottom: 1px solid #ddd; - margin: 0 0 1.625em; - padding: 0 0 1.625em; - position: relative; -} -.hentry:last-child, -.no-results { - border-bottom: none; -} -.blog .sticky .entry-header .entry-meta { - clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ - clip: rect(1px, 1px, 1px, 1px); - position: absolute !important; -} -.entry-title, -.entry-header .entry-meta { - padding-right: 76px; -} -.entry-title { - clear: both; - color: #222; - font-size: 26px; - font-weight: bold; - line-height: 1.5em; - padding-bottom: .3em; - padding-top: 15px; -} -.entry-title, -.entry-title a { - color: #222; - text-decoration: none; -} -.entry-title a:hover, -.entry-title a:focus, -.entry-title a:active { - color: #1982d1; -} -.entry-meta { - color: #666; - clear: both; - font-size: 12px; - line-height: 18px; -} -.entry-meta a { - font-weight: bold; -} -.single-author .entry-meta .by-author { - display: none; -} -.entry-content, -.entry-summary { - padding: 1.625em 0 0; -} -.entry-content h1, -.entry-content h2, -.comment-content h1, -.comment-content h2 { - color: #000; - font-weight: bold; - margin: 0 0 .8125em; -} -.entry-content h3, -.comment-content h3 { - font-size: 10px; - letter-spacing: 0.1em; - line-height: 2.6em; - text-transform: uppercase; -} -.entry-content table, -.comment-content table { - border-bottom: 1px solid #ddd; - margin: 0 0 1.625em; - width: 100%; -} -.entry-content th, -.comment-content th { - color: #666; - font-size: 10px; - font-weight: 500; - letter-spacing: 0.1em; - line-height: 2.6em; - text-transform: uppercase; -} -.entry-content td, -.comment-content td { - border-top: 1px solid #ddd; - padding: 6px 10px 6px 0; -} -.entry-content #s { - width: 75%; -} -.comment-content ul, -.comment-content ol { - margin-bottom: 1.625em; -} -.comment-content ul ul, -.comment-content ol ol, -.comment-content ul ol, -.comment-content ol ul { - margin-bottom: 0; -} -dl.gallery-item { - margin: 0; -} -.page-link { - clear: both; - display: block; - margin: 0 0 1.625em; -} -.page-link a { - background: #eee; - color: #373737; - margin: 0; - padding: 2px 3px; - text-decoration: none; -} -.page-link a:hover { - background: #888; - color: #fff; - font-weight: bold; -} -.page-link span { - margin-right: 6px; -} -.entry-meta .edit-link a, -.commentlist .edit-link a { - background: #eee; - -moz-border-radius: 3px; - border-radius: 3px; - color: #666; - float: right; - font-size: 12px; - line-height: 1.5em; - font-weight: 300; - text-decoration: none; - padding: 0 8px; -} -.entry-meta .edit-link a:hover, -.commentlist .edit-link a:hover { - background: #888; - color: #fff; -} -.entry-content .edit-link { - clear: both; - display: block; -} - -/* Images */ -.entry-content img, -.comment-content img, -.widget img { - max-width: 97.5%; /* Fluid images for posts, comments, and widgets */ -} -img[class*="align"], -img[class*="wp-image-"], -img[class*="attachment-"] { - height: auto; /* Make sure images with WordPress-added height and width attributes are scaled correctly */ -} -img.size-full, -img.size-large { - max-width: 97.5%; - width: auto; /* Prevent stretching of full-size and large-size images with height and width attributes in IE8 */ - height: auto; /* Make sure images with WordPress-added height and width attributes are scaled correctly */ -} -.entry-content img.wp-smiley { - border: none; - margin-bottom: 0; - margin-top: 0; - padding: 0; -} -img.alignleft, -img.alignright, -img.aligncenter { - margin-bottom: 1.625em; -} -p img, -.wp-caption { - margin-top: 0.4em; -} -.wp-caption { - background: #eee; - margin-bottom: 1.625em; - max-width: 96%; - padding: 9px; -} -.wp-caption img { - display: block; - margin: 0 auto; - max-width: 98%; -} -.wp-caption .wp-caption-text, -.gallery-caption { - color: #666; - font-family: Georgia, serif; - font-size: 12px; -} -.wp-caption .wp-caption-text { - margin-bottom: 0.6em; - padding: 10px 0 5px 40px; - position: relative; -} -.wp-caption .wp-caption-text:before { - color: #666; - content: '\2014'; - font-size: 14px; - font-style: normal; - font-weight: bold; - margin-right: 5px; - position: absolute; - left: 10px; - top: 7px; -} -#content .gallery { - margin: 0 auto 1.625em; -} -#content .gallery a img { - border: none; -} -img#wpstats { - display: block; - margin: 0 auto 1.625em; -} -#content .gallery-columns-4 .gallery-item { - width: 23%; - padding-right: 2%; -} -#content .gallery-columns-4 .gallery-item img { - width: 100%; - height: auto; -} - -/* Image borders */ -img[class*="align"], -img[class*="wp-image-"], -#content .gallery .gallery-icon img {/* Add fancy borders to all WordPress-added images but not things like badges and icons and the like */ - border: 1px solid #ddd; - padding: 6px; -} -.wp-caption img { - border-color: #eee; -} -a:focus img[class*="align"], -a:hover img[class*="align"], -a:active img[class*="align"], -a:focus img[class*="wp-image-"], -a:hover img[class*="wp-image-"], -a:active img[class*="wp-image-"], -#content .gallery .gallery-icon a:focus img, -#content .gallery .gallery-icon a:hover img, -#content .gallery .gallery-icon a:active img {/* Add some useful style to those fancy borders for linked images ... */ - background: #eee; - border-color: #bbb; -} -.wp-caption a:focus img, -.wp-caption a:active img, -.wp-caption a:hover img {/* ... including captioned images! */ - background: #fff; - border-color: #ddd; -} - -/* Make sure embeds and iframes fit their containers */ -embed, -iframe, -object { - max-width: 100%; -} - -/* Password Protected Posts */ -.post-password-required .entry-header .comments-link { - margin: 1.625em 0 0; -} -.post-password-required input[type=password] { - margin: 0.8125em 0; -} -.post-password-required input[type=password]:focus { - background: #f7f7f7; -} - -/* Author Info */ -#author-info { - font-size: 12px; - overflow: hidden; -} -.singular #author-info { - background: #f9f9f9; - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 2.2em -35.6% 0 -35.4%; - padding: 20px 35.4%; -} -.archive #author-info { - border-bottom: 1px solid #ddd; - margin: 0 0 2.2em; - padding: 0 0 2.2em; -} -#author-avatar { - float: left; - margin-right: -78px; -} -#author-avatar img { - background: #fff; - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0 1px 2px #bbb; - -moz-box-shadow: 0 1px 2px #bbb; - box-shadow: 0 1px 2px #bbb; - padding: 3px; -} -#author-description { - float: left; - margin-left: 108px; -} -#author-description h2 { - color: #000; - font-size: 15px; - font-weight: bold; - margin: 5px 0 10px; -} - -/* Comments link */ -.entry-header .comments-link a { - background: #eee url(images/comment-bubble.png) no-repeat; - color: #666; - font-size: 13px; - font-weight: normal; - line-height: 35px; - overflow: hidden; - padding: 0 0 0; - position: absolute; - top: 1.5em; - right: 0; - text-align: center; - text-decoration: none; - width: 43px; - height: 36px; -} -.entry-header .comments-link a:hover, -.entry-header .comments-link a:focus, -.entry-header .comments-link a:active { - background-color: #1982d1; - color: #fff; - color: rgba(255,255,255,0.8); -} -.entry-header .comments-link .leave-reply { - visibility: hidden; -} - -/* -Post Formats Headings -To hide the headings, display: none the ".entry-header .entry-format" selector, -and remove the padding rules below. -*/ -.entry-header .entry-format { - color: #666; - font-size: 10px; - font-weight: 500; - letter-spacing: 0.1em; - line-height: 2.6em; - position: absolute; - text-transform: uppercase; - top: -5px; -} -.entry-header hgroup .entry-title { - padding-top: 15px; -} -article.format-aside .entry-content, -article.format-link .entry-content, -article.format-status .entry-content { - padding: 20px 0 0; -} -article.format-status .entry-content { - min-height: 65px; -} -.recent-posts .entry-header .entry-format { - display: none; -} -.recent-posts .entry-header hgroup .entry-title { - padding-top: 0; -} - -/* Singular content styles for Posts and Pages */ -.singular .hentry { - border-bottom: none; - padding: 4.875em 0 0; - position: relative; -} -.singular.page .hentry { - padding: 3.5em 0 0; -} -.singular .entry-title { - color: #000; - font-size: 36px; - font-weight: bold; - line-height: 48px; -} -.singular .entry-title, -.singular .entry-header .entry-meta { - padding-right: 0; -} -.singular .entry-header .entry-meta { - position: absolute; - top: 0; - left: 0; -} -blockquote.pull { - font-size: 21px; - font-weight: bold; - line-height: 1.6125em; - margin: 0 0 1.625em; - text-align: center; -} -.singular blockquote.pull { - margin: 0 -22.25% 1.625em; -} -.pull.alignleft { - margin: 0 1.625em 0 0; - text-align: right; - width: 33%; -} -.singular .pull.alignleft { - margin: 0 1.625em 0 -22.25%; -} -.pull.alignright { - margin: 0 0 0 1.625em; - text-align: left; - width: 33%; -} -.singular .pull.alignright { - margin: 0 -22.25% 0 1.625em; -} -.singular blockquote.pull.alignleft, -.singular blockquote.pull.alignright { - width: 33%; -} -.singular .entry-meta .edit-link a { - bottom: auto; - left: 50px; - position: absolute; - right: auto; - top: 80px; -} - - -/* =Aside ------------------------------------------------ */ - -.format-aside .entry-title, -.format-aside .entry-header .comments-link { - display: none; -} -.singular .format-aside .entry-title { - display: block; -} -.format-aside .entry-content { - padding: 0; -} -.singular .format-aside .entry-content { - padding: 1.625em 0 0; -} - - -/* =Link ------------------------------------------------ */ - -.format-link .entry-title, -.format-link .entry-header .comments-link { - display: none; -} -.singular .format-link .entry-title { - display: block; -} -.format-link .entry-content { - padding: 0; -} -.singular .format-link .entry-content { - padding: 1.625em 0 0; -} - - -/* =Gallery ------------------------------------------------ */ - -.format-gallery .gallery-thumb { - float: left; - display: block; - margin: .375em 1.625em 0 0; -} - - -/* =Status ------------------------------------------------ */ - -.format-status .entry-title, -.format-status .entry-header .comments-link { - display: none; -} -.singular .format-status .entry-title { - display: block; -} -.format-status .entry-content { - padding: 0; -} -.singular .format-status .entry-content { - padding: 1.625em 0 0; -} -.format-status img.avatar { - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0 1px 2px #ccc; - -moz-box-shadow: 0 1px 2px #ccc; - box-shadow: 0 1px 2px #ccc; - float: left; - margin: 4px 10px 2px 0; - padding: 0; -} - - -/* =Quote ------------------------------------------------ */ - -.format-quote blockquote { - color: #555; - font-size: 17px; - margin: 0; -} - - -/* =Image ------------------------------------------------ */ - -.indexed.format-image .entry-header { - min-height: 61px; /* Prevent the comment icon from colliding with the image when there is no title */ -} -.indexed.format-image .entry-content { - padding-top: 0.5em; -} -.indexed.format-image p, -.indexed.format-image p img { - margin-bottom: 0; -} -.indexed.format-image footer.entry-meta { - background: #ddd; - margin-top: -7px; - padding: 20px 30px; - overflow: hidden; -} -.indexed.format-image div.entry-meta { - display: inline-block; - float: left; - width: 35%; -} -.indexed.format-image div.entry-meta + div.entry-meta { - float: none; - width: 65%; -} -.indexed.format-image .entry-meta span.cat-links, -.indexed.format-image .entry-meta span.tag-links, -.indexed.format-image .entry-meta span.comments-link { - display: block; -} -.indexed.format-image footer.entry-meta a { - color: #444; -} -.indexed.format-image footer.entry-meta a:hover { - color: #fff; -} -#content .indexed.format-image img { - border: none; - max-width: 100%; - padding: 0; -} -.indexed.format-image .wp-caption { - background: #111; - margin-bottom: 0; - max-width: 96%; - padding: 11px; -} -.indexed.format-image .wp-caption .wp-caption-text { - color: #ddd; -} -.indexed.format-image .wp-caption .wp-caption-text:before { - color: #444; -} -.indexed.format-image a:hover img { - opacity: 0.8; -} - - -/* =error404 ------------------------------------------------ */ - -.error404 #main #searchform { - background: #f9f9f9; - border: 1px solid #ddd; - border-width: 1px 0; - margin: 0 -8.9% 1.625em; - overflow: hidden; - padding: 1.625em 8.9%; -} -.error404 #main #s { - width: 95%; -} -.error404 #main .widget { - clear: none; - float: left; - margin-right: 3.7%; - width: 30.85%; -} -.error404 #main .widget_archive { - margin-right: 0; -} -.error404 #main .widget_tag_cloud { - float: none; - margin-right: 0; - width: 100%; -} -.error404 .widgettitle { - font-size: 10px; - letter-spacing: 0.1em; - line-height: 2.6em; - text-transform: uppercase; -} - - -/* =Showcase ------------------------------------------------ */ - -h1.showcase-heading { - color: #666; - font-size: 10px; - font-weight: 500; - letter-spacing: 0.1em; - line-height: 2.6em; - text-transform: uppercase; -} - -/* Intro */ -article.intro { - background: #f9f9f9; - border-bottom: none; - margin: -1.855em -8.9% 1.625em; - padding: 0 8.9%; -} -article.intro .entry-title { - display: none; -} -article.intro .entry-content { - color: #111; - font-size: 16px; - padding: 1.625em 0 0.625em; -} -article.intro .edit-link a { - background: #aaa; - -moz-border-radius: 3px; - border-radius: 3px; - color: #fff; - font-size: 12px; - padding: 0 8px; - position: absolute; - top: 30px; - right: 20px; - text-decoration: none; -} -article.intro .edit-link a:hover, -article.intro .edit-link a:focus, -article.intro .edit-link a:active { - background: #777; -} - -/* Featured post */ -section.featured-post { - float: left; - margin: -1.625em -8.9% 1.625em; - padding: 1.625em 8.9% 0; - position: relative; - width: 100%; -} -section.featured-post .hentry { - border: none; - color: #666; - margin: 0; -} -section.featured-post .entry-meta { - clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ - clip: rect(1px, 1px, 1px, 1px); - position: absolute !important; -} - -/* Small featured post */ -section.featured-post .attachment-small-feature { - float: right; - height: auto; - margin: 0 -8.9% 1.625em 0; - max-width: 59%; - position: relative; - right: -15px; -} -section.featured-post.small { - padding-top: 0; -} -section.featured-post .attachment-small-feature:hover, -section.featured-post .attachment-small-feature:focus, -section.featured-post .attachment-small-feature:active { - opacity: .8; -} -article.feature-image.small { - float: left; - margin: 0 0 1.625em; - width: 45%; -} -article.feature-image.small .entry-title { - line-height: 1.2em; -} -article.feature-image.small .entry-summary { - color: #555; - font-size: 13px; -} -article.feature-image.small .entry-summary p a { - background: #222; - color: #eee; - display: block; - left: -23.8%; - padding: 9px 26px 9px 85px; - position: relative; - text-decoration: none; - top: 20px; - width: 180px; - z-index: 1; -} -article.feature-image.small .entry-summary p a:hover { - background: #1982d1; - color: #eee; - color: rgba(255,255,255,0.8); -} - -/* Large featured post */ -section.feature-image.large { - border: none; - max-height: 288px; - padding: 0; - width: 100%; -} -section.feature-image.large .showcase-heading { - display: none; -} -section.feature-image.large .hentry { - border-bottom: none; - left: 9%; - margin: 1.625em 9% 0 0; - position: absolute; - top: 0; -} -article.feature-image.large .entry-title a { - background: #222; - background: rgba(0,0,0,0.8); - -moz-border-radius: 3px; - border-radius: 3px; - color: #fff; - display: inline-block; - font-weight: 300; - padding: .2em 20px; -} -section.feature-image.large:hover .entry-title a, -section.feature-image.large .entry-title:hover a { - background: #eee; - background: rgba(255,255,255,0.8); - color: #222; -} -article.feature-image.large .entry-summary { - display: none; -} -section.feature-image.large img { - display: block; - height: auto; - max-width: 117.9%; - padding: 0 0 6px; -} - -/* Featured Slider */ -.featured-posts { - border-bottom: 1px solid #ddd; - display: block; - height: 328px; - margin: 1.625em -8.9% 20px; - max-width: 1000px; - padding: 0; - position: relative; - overflow: hidden; -} -.featured-posts .showcase-heading { - padding-left: 8.9%; -} -.featured-posts section.featured-post { - background: #fff; - height: 288px; - left: 0; - margin: 0; - position: absolute; - top: 30px; - width: auto; -} -.featured-posts section.featured-post.large { - max-width: 100%; - overflow: hidden; -} -.featured-posts section.featured-post { - -webkit-transition-duration: 200ms; - -webkit-transition-property: opacity, visibility; - -webkit-transition-timing-function: ease; - -moz-transition-duration: 200ms; - -moz-transition-property: opacity, visibility; - -moz-transition-timing-function: ease; -} -.featured-posts section.featured-post { - opacity: 0; - visibility: hidden; -} -.featured-posts #featured-post-1 { - opacity: 1; - visibility: visible; -} -.featured-post .feature-text:after, -.featured-post .feature-image.small:after { - content: ' '; - background: -moz-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,0)), color-stop(100%,rgba(255,255,255,1))); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#ffffff',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* W3C */ - width: 100%; - height: 45px; - position: absolute; - top: 230px; -} -.featured-post .feature-image.small:after { - top: 253px; -} -#content .feature-slider { - top: 5px; - right: 8.9%; - overflow: visible; - position: absolute; -} -.feature-slider ul { - list-style-type: none; - margin: 0; -} -.feature-slider li { - float: left; - margin: 0 6px; -} -.feature-slider a { - background: #3c3c3c; - background: rgba(60,60,60,0.9); - -moz-border-radius: 12px; - border-radius: 12px; - -webkit-box-shadow: inset 1px 1px 5px rgba(0,0,0,0.5), inset 0 0 2px rgba(255,255,255,0.5); - -moz-box-shadow: inset 1px 1px 5px rgba(0,0,0,0.5), inset 0 0 2px rgba(255,255,255,0.5); - box-shadow: inset 1px 1px 5px rgba(0,0,0,0.5), inset 0 0 2px rgba(255,255,255,0.5); - display: block; - width: 14px; - height: 14px; -} -.feature-slider a.active { - background: #1982d1; - -webkit-box-shadow: inset 1px 1px 5px rgba(0,0,0,0.4), inset 0 0 2px rgba(255,255,255,0.8); - -moz-box-shadow: inset 1px 1px 5px rgba(0,0,0,0.4), inset 0 0 2px rgba(255,255,255,0.8); - box-shadow: inset 1px 1px 5px rgba(0,0,0,0.4), inset 0 0 2px rgba(255,255,255,0.8); - cursor: default; - opacity: 0.5; -} - -/* Recent Posts */ -section.recent-posts { - padding: 0 0 1.625em; -} -section.recent-posts .hentry { - border: none; - margin: 0; -} -section.recent-posts .other-recent-posts { - border-bottom: 1px solid #ddd; - list-style: none; - margin: 0; -} -section.recent-posts .other-recent-posts li { - padding: 0.3125em 0; - position: relative; -} -section.recent-posts .other-recent-posts .entry-title { - border-top: 1px solid #ddd; - font-size: 17px; -} -section.recent-posts .other-recent-posts a[rel="bookmark"] { - color: #373737; - float: left; - max-width: 84%; -} -section.recent-posts .other-recent-posts a[rel="bookmark"]:after { - content: '-'; - color: transparent; - font-size: 11px; -} -section.recent-posts .other-recent-posts a[rel="bookmark"]:hover { -} -section.recent-posts .other-recent-posts .comments-link a, -section.recent-posts .other-recent-posts .comments-link > span { - border-bottom: 2px solid #999; - bottom: -2px; - color: #444; - display: block; - font-size: 10px; - font-weight: 500; - line-height: 2.76333em; - padding: 0.3125em 0 0.3125em 1em; - position: absolute; - right: 0; - text-align: right; - text-transform: uppercase; - z-index: 1; -} -section.recent-posts .other-recent-posts .comments-link > span { - border-color: #bbb; - color: #888; -} -section.recent-posts .other-recent-posts .comments-link a:hover { - color: #1982d1; - border-color: #1982d1; -} -section.recent-posts .other-recent-posts li:after { - clear: both; - content: '.'; - display: block; - height: 0; - visibility: hidden; -} - - -/* =Attachments ------------------------------------------------ */ - -.image-attachment div.attachment { - background: #f9f9f9; - border: 1px solid #ddd; - border-width: 1px 0; - margin: 0 -8.9% 1.625em; - overflow: hidden; - padding: 1.625em 1.625em 0; - text-align: center; -} -.image-attachment div.attachment img { - display: block; - height: auto; - margin: 0 auto 1.625em; - max-width: 100%; -} -.image-attachment div.attachment a img { - border-color: #f9f9f9; -} -.image-attachment div.attachment a:focus img, -.image-attachment div.attachment a:hover img, -.image-attachment div.attachment a:active img { - border-color: #ddd; - background: #fff; -} -.image-attachment .entry-caption p { - font-size: 10px; - letter-spacing: 0.1em; - line-height: 2.6em; - margin: 0 0 2.6em; - text-transform: uppercase; -} - - -/* =Navigation --------------------------------------------------------------- */ - -#content nav { - clear: both; - overflow: hidden; - padding: 0 0 1.625em; -} -#content nav a { - font-size: 12px; - font-weight: bold; - line-height: 2.2em; -} -#nav-above { - padding: 0 0 1.625em; -} -#nav-above { - display: none; -} -.paged #nav-above { - display: block; -} -.nav-previous { - float: left; - width: 50%; -} -.nav-next { - float: right; - text-align: right; - width: 50%; -} -#content nav .meta-nav { - font-weight: normal; -} - -/* Singular navigation */ -#nav-single { - float: right; - position: relative; - top: -0.3em; - text-align: right; - z-index: 1; -} -#nav-single .nav-previous, -#nav-single .nav-next { - float: none; - width: auto; -} -#nav-single .nav-next { - padding-left: .5em; -} - - -/* =Widgets ------------------------------------------------ */ - -.widget-area { - font-size: 12px; -} -.widget { - clear: both; - margin: 0 0 2.2em; -} -.widget-title { - color: #666; - font-size: 10px; - font-weight: 500; - letter-spacing: 0.1em; - line-height: 2.6em; - text-transform: uppercase; -} -.widget ul { - font-size: 15px; - margin: 0; -} -.widget ul ul { - margin-left: 1.5em; -} -.widget ul li { - color: #777; - font-size: 13px; -} -.widget a { - font-weight: bold; - text-decoration: none; -} -.widget a:hover, -.widget a:focus, -.widget a:active { - text-decoration: underline; -} - -/* Search Widget */ -.widget_search form { - margin: 0 0 1.625em; -} -.widget_search #s { - width: 77%; -} -.widget_search #searchsubmit { - background: #ddd; - border: 1px solid #ccc; - -webkit-box-shadow: inset 0px -1px 1px rgba(0, 0, 0, 0.09); - -moz-box-shadow: inset 0px -1px 1px rgba(0, 0, 0, 0.09); - box-shadow: inset 0px -1px 1px rgba(0, 0, 0, 0.09); - color: #888; - font-size: 13px; - line-height: 25px; - position: relative; - top: -2px; -} -.widget_search #searchsubmit:active { - background: #1982d1; - border-color: #0861a5; - -webkit-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.1); - box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.1); - color: #bfddf3; -} - -/* Ephemera Widget */ -section.ephemera ol, -.widget_twentyeleven_ephemera ol { - list-style: square; - margin: 5px 0 0; -} -.widget_twentyeleven_ephemera .widget-entry-title { - font-size: 15px; - font-weight: bold; - padding: 0; -} -.widget_twentyeleven_ephemera .comments-link a, -.widget_twentyeleven_ephemera .comments-link > span { - color: #666; - display: block; - font-size: 10px; - font-weight: 500; - line-height: 2.76333em; - text-transform: uppercase; -} -section.ephemera .entry-title .comments-link a:hover, -.widget_twentyeleven_ephemera .entry-title .comments-link a:hover { -} -section.ephemera .entry-title a span { - color: #29628d; -} - -/* Twitter */ -.widget_twitter li { - list-style-type: none; - margin-bottom: 14px; -} -.widget_twitter .timesince { - display: block; - font-size: 11px; - margin-right: -10px; - text-align: right; -} - -/* Widget Image */ -.widget_image img { - height: auto; - max-width: 100%; -} - -/* Calendar Widget */ - -.widget_calendar #wp-calendar { - color: #555; - width: 95%; - text-align: center; -} -.widget_calendar #wp-calendar caption, -.widget_calendar #wp-calendar td, -.widget_calendar #wp-calendar th { - text-align: center; -} -.widget_calendar #wp-calendar caption { - font-size: 11px; - font-weight: 500; - padding: 5px 0 3px 0; - text-transform: uppercase; -} -.widget_calendar #wp-calendar th { - background: #f4f4f4; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; - font-weight: bold; -} -.widget_calendar #wp-calendar tfoot td { - background: #f4f4f4; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; -} - - -/* =Comments ------------------------------------------------ */ - -#comments-title { - color: #666; - font-size: 10px; - font-weight: 500; - line-height: 2.6em; - padding: 0 0 2.6em; - text-transform: uppercase; -} -.nopassword, -.nocomments { - color: #aaa; - font-size: 24px; - font-weight: 100; - margin: 26px 0; - text-align: center; -} -.commentlist { - list-style: none; - margin: 0 auto; - width: 68.9%; -} -.content .commentlist, -.page-template-sidebar-page-php .commentlist { - width: 100%; /* reset the width for the one-column and sidebar page layout */ -} -.commentlist > li.comment { - background: #f6f6f6; - border: 1px solid #ddd; - -moz-border-radius: 3px; - border-radius: 3px; - margin: 0 0 1.625em; - padding: 1.625em; - position: relative; -} -.commentlist .pingback { - margin: 0 0 1.625em; - padding: 0 1.625em; -} -.commentlist .children { - list-style: none; - margin: 0; -} -.commentlist .children li.comment { - background: #fff; - border-left: 1px solid #ddd; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; - margin: 1.625em 0 0; - padding: 1.625em; - position: relative; -} -.commentlist .children li.comment .fn { - display: block; -} -.comment-meta .fn { - font-style: normal; -} -.comment-meta { - color: #666; - font-size: 12px; - line-height: 2.2em; -} -.commentlist .children li.comment .comment-meta { - line-height: 1.625em; - margin-left: 50px; -} -.commentlist .children li.comment .comment-content { - margin: 1.625em 0 0; -} -.comment-meta a { - font-weight: bold; -} -.comment-meta a:focus, -.comment-meta a:active, -.comment-meta a:hover { -} -.commentlist .avatar { - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0 1px 2px #ccc; - -moz-box-shadow: 0 1px 2px #ccc; - box-shadow: 0 1px 2px #ccc; - left: -102px; - padding: 0; - position: absolute; - top: 0; -} -.commentlist > li:before { - content: url(images/comment-arrow.png); - left: -21px; - position: absolute; -} -.commentlist > li.pingback:before { - content: ''; -} -.commentlist .children .avatar { - background: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - left: 2.2em; - padding: 0; - top: 2.2em; -} -a.comment-reply-link { - background: #eee; - -moz-border-radius: 3px; - border-radius: 3px; - color: #666; - display: inline-block; - font-size: 12px; - padding: 0 8px; - text-decoration: none; -} -a.comment-reply-link:hover, -a.comment-reply-link:focus, -a.comment-reply-link:active { - background: #888; - color: #fff; -} -a.comment-reply-link > span { - display: inline-block; - position: relative; - top: -1px; -} - -/* Post author highlighting */ -.commentlist > li.bypostauthor { - background: #ddd; - border-color: #d3d3d3; -} -.commentlist > li.bypostauthor .comment-meta { - color: #575757; -} -.commentlist > li.bypostauthor .comment-meta a:focus, -.commentlist > li.bypostauthor .comment-meta a:active, -.commentlist > li.bypostauthor .comment-meta a:hover { -} -.commentlist > li.bypostauthor:before { - content: url(images/comment-arrow-bypostauthor.png); -} - -/* Post Author threaded comments */ -.commentlist .children > li.bypostauthor { - background: #ddd; - border-color: #d3d3d3; -} - -/* sidebar-page.php comments */ -/* Make sure we have room for our comment avatars */ -.page-template-sidebar-page-php .commentlist > li.comment, -.page-template-sidebar-page-php.commentlist .pingback { - margin-left: 102px; - width: auto; -} -/* And a full-width comment form */ -.page-template-sidebar-page-php #respond { - width: auto; -} - -/* Comment Form */ -#respond { - background: #ddd; - border: 1px solid #d3d3d3; - -moz-border-radius: 3px; - border-radius: 3px; - margin: 0 auto 1.625em; - padding: 1.625em; - position: relative; - width: 68.9%; -} -#respond input[type="text"], -#respond textarea { - background: #fff; - border: 4px solid #eee; - -moz-border-radius: 5px; - border-radius: 5px; - -webkit-box-shadow: inset 0 1px 3px rgba(204,204,204,0.95); - -moz-box-shadow: inset 0 1px 3px rgba(204,204,204,0.95); - box-shadow: inset 0 1px 3px rgba(204,204,204,0.95); - position: relative; - padding: 10px; - text-indent: 80px; -} -#respond .comment-form-author, -#respond .comment-form-email, -#respond .comment-form-url, -#respond .comment-form-comment { - position: relative; -} -#respond .comment-form-author label, -#respond .comment-form-email label, -#respond .comment-form-url label, -#respond .comment-form-comment label { - background: #eee; - -webkit-box-shadow: 1px 2px 2px rgba(204,204,204,0.8); - -moz-box-shadow: 1px 2px 2px rgba(204,204,204,0.8); - box-shadow: 1px 2px 2px rgba(204,204,204,0.8); - color: #555; - display: inline-block; - font-size: 13px; - left: 4px; - min-width: 60px; - padding: 4px 10px; - position: relative; - top: 40px; - z-index: 1; -} -#respond input[type="text"]:focus, -#respond textarea:focus { - text-indent: 0; - z-index: 1; -} -#respond textarea { - resize: vertical; - width: 95%; -} -#respond .comment-form-author .required, -#respond .comment-form-email .required { - color: #bd3500; - font-size: 22px; - font-weight: bold; - left: 75%; - position: absolute; - top: 45px; - z-index: 1; -} -#respond .comment-notes, -#respond .logged-in-as { - font-size: 13px; -} -#respond p { - margin: 10px 0; -} -#respond .form-submit { - float: right; - margin: -20px 0 10px; -} -#respond input#submit { - background: #222; - border: none; - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0px 1px 2px rgba(0,0,0,0.3); - -moz-box-shadow: 0px 1px 2px rgba(0,0,0,0.3); - box-shadow: 0px 1px 2px rgba(0,0,0,0.3); - color: #eee; - cursor: pointer; - font-size: 15px; - margin: 20px 0; - padding: 5px 42px 5px 22px; - position: relative; - left: 30px; - text-shadow: 0 -1px 0 rgba(0,0,0,0.3); -} -#respond input#submit:active { - background: #1982d1; - color: #bfddf3; -} -#respond #cancel-comment-reply-link { - color: #666; - margin-left: 10px; - text-decoration: none; -} -#respond .logged-in-as a:hover, -#respond #cancel-comment-reply-link:hover { - text-decoration: underline; -} -.commentlist #respond { - margin: 1.625em 0 0; - width: auto; -} -#reply-title { - color: #373737; - font-size: 24px; - font-weight: bold; - line-height: 30px; -} -#cancel-comment-reply-link { - color: #888; - display: block; - font-size: 10px; - font-weight: normal; - line-height: 2.2em; - letter-spacing: 0.05em; - position: absolute; - right: 1.625em; - text-decoration: none; - text-transform: uppercase; - top: 1.1em; -} -#cancel-comment-reply-link:focus, -#cancel-comment-reply-link:active, -#cancel-comment-reply-link:hover { - color: #ff4b33; -} -#respond label { - line-height: 2.2em; -} -#respond input[type=text] { - display: block; - height: 24px; - width: 75%; -} -#respond p { - font-size: 12px; -} -p.comment-form-comment { - margin: 0; -} -.form-allowed-tags { - display: none; -} - - -/* =Footer ------------------------------------------------ */ - -#colophon { - clear: both; -} -#supplementary { - border-top: 1px solid #ddd; - padding: 1.625em 7.6%; - overflow: hidden; -} - -/* Two Footer Widget Areas */ -#supplementary.two .widget-area { - float: left; - margin-right: 3.7%; - width: 48.1%; -} -#supplementary.two .widget-area + .widget-area { - margin-right: 0; -} - -/* Three Footer Widget Areas */ -#supplementary.three .widget-area { - float: left; - margin-right: 3.7%; - width: 30.85%; -} -#supplementary.three .widget-area + .widget-area + .widget-area { - margin-right: 0; -} - -/* Site Generator Line */ -#site-generator { - background: #f9f9f9; - border-top: 1px solid #ddd; - color: #666; - font-size: 12px; - line-height: 2.2em; - padding: 2.2em 0.5em; - text-align: center; -} -#site-generator a { - color: #555; - font-weight: bold; -} -#site-generator .sep { - background: url(images/wordpress.png) center left no-repeat; - color: transparent; - display: inline-block; - height: 16px; - line-height: 16px; - margin: 0 7px; - width: 16px; -} - - -/* =Responsive Structure ------------------------------------------------ */ - -@media (max-width: 800px) { - /* Simplify the basic layout */ - #main #content { - margin: 0 7.6%; - width: auto; - } - #nav-below { - border-bottom: 1px solid #ddd; - margin-bottom: 1.625em; - } - #main #secondary { - float: none; - margin: 0 7.6%; - width: auto; - } - /* Simplify the showcase template */ - .page-template-showcase-php .featured-posts { - min-height: 280px; - } - .featured-posts section.featured-post { - height: auto; - } - .page-template-showcase-php section.recent-posts { - float: none; - margin: 0; - width: 100%; - } - .page-template-showcase-php #main .widget-area { - float: none; - margin: 0; - width: auto; - } - .page-template-showcase-php .other-recent-posts { - border-bottom: 1px solid #ddd; - } - /* Simplify the showcase template when small feature */ - section.featured-post .attachment-small-feature, - .one-column section.featured-post .attachment-small-feature { - border: none; - display: block; - float: left; - height: auto; - margin: 0.625em auto 1.025em; - max-width: 30%; - position: static; - } - article.feature-image.small { - float: right; - margin: 0 0 1.625em; - width: 64%; - } - .one-column article.feature-image.small .entry-summary { - height: auto; - } - article.feature-image.small .entry-summary p a { - left: 0; - padding-left: 20px; - padding-right: 20px; - width: auto; - } - /* Remove the margin on singular articles */ - .singular .entry-header, - .singular .entry-content, - .singular footer.entry-meta, - .singular #comments-title { - width: 100%; - } - /* Simplify the pullquotes and pull styles */ - .singular blockquote.pull { - margin: 0 0 1.625em; - } - .singular .pull.alignleft { - margin: 0 1.625em 0 0; - } - .singular .pull.alignright { - margin: 0 0 0 1.625em; - } - .singular .entry-meta .edit-link a { - left: 0; - position: absolute; - top: 40px; - } - .singular #author-info { - margin: 2.2em -8.8% 0; - padding: 20px 8.8%; - } - /* Make sure we have room for our comment avatars */ - .commentlist { - width: 100%; - } - .commentlist > li.comment, - .commentlist .pingback { - margin-left: 102px; - width: auto; - } - /* And a full-width comment form */ - #respond { - width: auto; - } - /* No need to float footer widgets at this size */ - #colophon #supplementary .widget-area { - float: none; - margin-right: 0; - width: auto; - } - /* No need to float 404 widgets at this size */ - .error404 #main .widget { - float: none; - margin-right: 0; - width: auto; - } - -} -@media (max-width: 650px) { - /* @media (max-width: 650px) Reduce font-sizes for better readability on smaller devices */ - body, input, textarea { - font-size: 13px; - } - #site-title a { - font-size: 24px; - } - #site-description { - font-size: 12px; - } - #access ul { - font-size: 12px; - } - article.intro .entry-content { - font-size: 12px; - } - .entry-title { - font-size: 21px; - } - .featured-post .entry-title { - font-size: 14px; - } - .singular .entry-title { - font-size: 28px; - } - .entry-meta { - font-size: 12px; - } - blockquote { - margin: 0; - } - blockquote.pull { - font-size: 17px; - } - /* Reposition the site title and description slightly */ - #site-title { - padding: 5.30625em 0 0; - } - #site-title, - #site-description { - margin-right: 0; - } - /* Make sure the logo and search form don't collide */ - #branding #searchform { - top: 1.625em !important; - } - /* Floated content doesn't work well at this size */ - .alignleft, - .alignright { - float: none; - margin-left: 0; - margin-right: 0; - } - /* Make sure the post-post navigation doesn't collide with anything */ - #nav-single { - display: block; - position: static; - } - .singular .hentry { - padding: 1.625em 0 0; - } - .singular.page .hentry { - padding: 1.625em 0 0; - } - /* Talking avatars take up too much room at this size */ - .commentlist > li.comment, - .commentlist > li.pingback { - margin-left: 0 !important; - } - .commentlist .avatar { - background: transparent; - display: block; - padding: 0; - position: static; - } - .commentlist .children .avatar { - background: none; - left: 2.2em; - padding: 0; - position: absolute; - top: 2.2em; - } - /* Use the available space in the smaller comment form */ - #respond input[type="text"] { - width: 95%; - } - #respond .comment-form-author .required, - #respond .comment-form-email .required { - left: 95%; - } - #content .gallery-columns-3 .gallery-item { - width: 31%; - padding-right: 2%; - } - #content .gallery-columns-3 .gallery-item img { - width: 100%; - height: auto; - } - -} -@media (max-width: 450px) { - #content .gallery-columns-2 .gallery-item { - width: 45%; - padding-right: 4%; - } - #content .gallery-columns-2 .gallery-item img { - width: 100%; - height: auto; - } - -} -@media only screen and (min-device-width: 320px) and (max-device-width: 480px) { - body { - padding: 0; - } - #page { - margin-top: 0; - } - #branding { - border-top: none; - } - -} - - -/* =Print ------------------------------------------------ */ - -@media print { - body { - background: none !important; - font-size: 10pt; - } - footer.entry-meta a[rel=bookmark]:link:after, - footer.entry-meta a[rel=bookmark]:visited:after { - content: " [" attr(href) "] "; /* Show URLs */ - } - #page { - clear: both !important; - display: block !important; - float: none !important; - max-width: 100%; - position: relative !important; - } - #branding { - border-top: none !important; - padding: 0; - } - #branding hgroup { - margin: 0; - } - #site-title a { - font-size: 21pt; - } - #site-description { - font-size: 10pt; - } - #branding #searchform { - display: none; - } - #branding img { - display: none; - } - #access { - display: none; - } - #main { - border-top: none; - box-shadow: none; - } - #primary { - float: left; - margin: 0; - width: 100%; - } - #content { - margin: 0; - width: auto; - } - .singular #content { - margin: 0; - width: 100%; - } - .singular .entry-header .entry-meta { - position: static; - } - .entry-meta .edit-link a { - display: none; - } - #content nav { - display: none; - } - .singular .entry-header, - .singular .entry-content, - .singular footer.entry-meta, - .singular #comments-title { - margin: 0; - width: 100%; - } - .singular .hentry { - padding: 0; - } - .entry-title, - .singular .entry-title { - font-size: 21pt; - } - .entry-meta { - font-size: 10pt; - } - .entry-header .comments-link { - display: none; - } - .page-link { - display: none; - } - .singular #author-info { - background: none; - border-bottom: none; - border-top: none; - margin: 2.2em 0 0; - padding: 0; - } - #respond { - display: none; - } - .widget-area { - display: none; - } - #colophon { - display: none; - } - - /* Comments */ - .commentlist > li.comment { - background: none; - border: 1px solid #ddd; - -moz-border-radius: 3px 3px 3px 3px; - border-radius: 3px 3px 3px 3px; - margin: 0 auto 1.625em; - padding: 1.625em; - position: relative; - width: auto; - } - .commentlist .avatar { - height: 39px; - left: 2.2em; - top: 2.2em; - width: 39px; - } - .commentlist li.comment .comment-meta { - line-height: 1.625em; - margin-left: 50px; - } - .commentlist li.comment .fn { - display: block; - } - .commentlist li.comment .comment-content { - margin: 1.625em 0 0; - } - .commentlist .comment-edit-link { - display: none; - } - .commentlist > li::before, - .commentlist > li.bypostauthor::before { - content: ''; - } - .commentlist .reply { - display: none; - } - - /* Post author highlighting */ - .commentlist > li.bypostauthor { - color: #444; - } - .commentlist > li.bypostauthor .comment-meta { - color: #666; - } - .commentlist > li.bypostauthor:before { - content: none; - } - - /* Post Author threaded comments */ - .commentlist .children > li.bypostauthor { - background: #fff; - border-color: #ddd; - } - .commentlist .children > li.bypostauthor > article, - .commentlist .children > li.bypostauthor > article .comment-meta { - color: #666; - } - -} - - -/* =IE7 ------------------------------------------------ */ - -#ie7 article.intro { - margin-left: -7.6%; - margin-right: -7.6%; - padding-left: -7.6%; - padding-right: -7.6%; - max-width: 1000px; -} -#ie7 section.featured-post { - margin-left: -7.6%; - margin-right: -7.6%; - max-width: 850px; -} -#ie7 section.recent-posts { - margin-right: 7.6%; -} diff --git a/spec/samples/common/models/wp_theme/versionable/twentyeleven-unknow.css b/spec/samples/common/models/wp_theme/versionable/twentyeleven-unknow.css deleted file mode 100644 index f9f820e9..00000000 --- a/spec/samples/common/models/wp_theme/versionable/twentyeleven-unknow.css +++ /dev/null @@ -1,2678 +0,0 @@ -/* -Theme Name: Twenty Eleven -Theme URI: http://wordpress.org/extend/themes/twentyeleven -Author: the WordPress team -Author URI: http://wordpress.org/ -Description: The 2011 theme for WordPress is sophisticated, lightweight, and adaptable. Make it yours with a custom menu, header image, and background -- then go further with available theme options for light or dark color scheme, custom link colors, and three layout choices. Twenty Eleven comes equipped with a Showcase page template that transforms your front page into a showcase to show off your best content, widget support galore (sidebar, three footer areas, and a Showcase page widget area), and a custom "Ephemera" widget to display your Aside, Link, Quote, or Status posts. Included are styles for print and for the admin editor, support for featured images (as custom header images on posts and pages and as large images on featured "sticky" posts), and special styles for six different post formats. -License: GNU General Public License -License URI: license.txt -Tags: dark, light, white, black, gray, one-column, two-columns, left-sidebar, right-sidebar, fixed-width, flexible-width, custom-background, custom-colors, custom-header, custom-menu, editor-style, featured-image-header, featured-images, full-width-template, microformats, post-formats, rtl-language-support, sticky-post, theme-options, translation-ready -*/ - -/* =Reset default browser CSS. Based on work by Eric Meyer: http://meyerweb.com/eric/tools/css/reset/index.html --------------------------------------------------------------- */ - -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, font, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td { - border: 0; - font-family: inherit; - font-size: 100%; - font-style: inherit; - font-weight: inherit; - margin: 0; - outline: 0; - padding: 0; - vertical-align: baseline; -} -:focus {/* remember to define focus styles! */ - outline: 0; -} -body { - background: #fff; - line-height: 1; -} -ol, ul { - list-style: none; -} -table {/* tables still need 'cellspacing="0"' in the markup */ - border-collapse: separate; - border-spacing: 0; -} -caption, th, td { - font-weight: normal; - text-align: left; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ""; -} -blockquote, q { - quotes: "" ""; -} -a img { - border: 0; -} -article, aside, details, figcaption, figure, -footer, header, hgroup, menu, nav, section { - display: block; -} - - -/* =Structure ------------------------------------------------ */ - -body { - padding: 0 2em; -} -#page { - margin: 2em auto; - max-width: 1000px; -} -#branding hgroup { - margin: 0 7.6%; -} -#access div { - margin: 0 7.6%; -} -#primary { - float: left; - margin: 0 -26.4% 0 0; - width: 100%; -} -#content { - margin: 0 34% 0 7.6%; - width: 58.4%; -} -#secondary { - float: right; - margin-right: 7.6%; - width: 18.8%; -} - -/* Singular */ -.singular #primary { - margin: 0; -} -.singular #content, -.left-sidebar.singular #content { - margin: 0 7.6%; - position: relative; - width: auto; -} -.singular .entry-header, -.singular .entry-content, -.singular footer.entry-meta, -.singular #comments-title { - margin: 0 auto; - width: 68.9%; -} - -/* Attachments */ -.singular .image-attachment .entry-content { - margin: 0 auto; - width: auto; -} -.singular .image-attachment .entry-description { - margin: 0 auto; - width: 68.9%; -} - -/* Showcase */ -.page-template-showcase-php #primary, -.left-sidebar.page-template-showcase-php #primary { - margin: 0; -} -.page-template-showcase-php #content, -.left-sidebar.page-template-showcase-php #content { - margin: 0 7.6%; - width: auto; -} -.page-template-showcase-php section.recent-posts { - float: right; - margin: 0 0 0 31%; - width: 69%; -} -.page-template-showcase-php #main .widget-area { - float: left; - margin: 0 -22.15% 0 0; - width: 22.15%; -} - -/* error404 */ -.error404 #primary { - float: none; - margin: 0; -} -.error404 #primary #content { - margin: 0 7.6%; - width: auto; -} - -/* Alignment */ -.alignleft { - display: inline; - float: left; - margin-right: 1.625em; -} -.alignright { - display: inline; - float: right; - margin-left: 1.625em; -} -.aligncenter { - clear: both; - display: block; - margin-left: auto; - margin-right: auto; -} - -/* Right Content */ -.left-sidebar #primary { - float: right; - margin: 0 0 0 -26.4%; - width: 100%; -} -.left-sidebar #content { - margin: 0 7.6% 0 34%; - width: 58.4%; -} -.left-sidebar #secondary { - float: left; - margin-left: 7.6%; - margin-right: 0; - width: 18.8%; -} - -/* One column */ -.one-column #page { - max-width: 690px; -} -.one-column #content { - margin: 0 7.6%; - width: auto; -} -.one-column #nav-below { - border-bottom: 1px solid #ddd; - margin-bottom: 1.625em; -} -.one-column #secondary { - float: none; - margin: 0 7.6%; - width: auto; -} -/* Simplify the showcase template */ -.one-column .page-template-showcase-php section.recent-posts { - float: none; - margin: 0; - width: 100%; -} -.one-column .page-template-showcase-php #main .widget-area { - float: none; - margin: 0; - width: auto; -} -.one-column .page-template-showcase-php .other-recent-posts { - border-bottom: 1px solid #ddd; -} -/* Simplify the showcase template when small feature */ -.one-column section.featured-post .attachment-small-feature { - border: none; - display: block; - height: auto; - max-width: 60%; - position: static; -} -.one-column article.feature-image.small { - margin: 0 0 1.625em; - padding: 0; -} -.one-column article.feature-image.small .entry-title { - font-size: 20px; - line-height: 1.3em; -} -.one-column article.feature-image.small .entry-summary { - height: 150px; - overflow: hidden; - padding: 0; - text-overflow: ellipsis; -} -.one-column article.feature-image.small .entry-summary a { - left: -9%; -} -/* Remove the margin on singular articles */ -.one-column.singular .entry-header, -.one-column.singular .entry-content, -.one-column.singular footer.entry-meta, -.one-column.singular #comments-title { - width: 100%; -} -/* Simplify the pullquotes and pull styles */ -.one-column.singular blockquote.pull { - margin: 0 0 1.625em; -} -.one-column.singular .pull.alignleft { - margin: 0 1.625em 0 0; -} -.one-column.singular .pull.alignright { - margin: 0 0 0 1.625em; -} -.one-column.singular .entry-meta .edit-link a { - position: absolute; - left: 0; - top: 40px; -} -.one-column.singular #author-info { - margin: 2.2em -8.8% 0; - padding: 20px 8.8%; -} -/* Make sure we have room for our comment avatars */ -.one-column .commentlist > li.comment { - margin-left: 102px; - width: auto; -} -/* Make sure the logo and search form don't collide */ -.one-column #branding #searchform { - right: 40px; - top: 4em; -} -/* Talking avatars take up too much room at this size */ -.one-column .commentlist > li.comment { - margin-left: 0; -} -.one-column .commentlist > li.comment .comment-meta, -.one-column .commentlist > li.comment .comment-content { - margin-right: 85px; -} -.one-column .commentlist .avatar { - background: transparent; - display: block; - padding: 0; - top: 1.625em; - left: auto; - right: 1.625em; -} -.one-column .commentlist .children .avatar { - background: none; - padding: 0; - position: absolute; - top: 2.2em; - left: 2.2em; -} -.one-column #respond { - width: auto; -} - - -/* =Global ------------------------------------------------ */ - -body, input, textarea { - color: #373737; - font: 15px "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: 300; - line-height: 1.625; -} -body { - background: #e2e2e2; -} -#page { - background: #fff; -} - -/* Headings */ -h1,h2,h3,h4,h5,h6 { - clear: both; -} -hr { - background-color: #ccc; - border: 0; - height: 1px; - margin-bottom: 1.625em; -} - -/* Text elements */ -p { - margin-bottom: 1.625em; -} -ul, ol { - margin: 0 0 1.625em 2.5em; -} -ul { - list-style: square; -} -ol { - list-style-type: decimal; -} -ol ol { - list-style: upper-alpha; -} -ol ol ol { - list-style: lower-roman; -} -ol ol ol ol { - list-style: lower-alpha; -} -ul ul, ol ol, ul ol, ol ul { - margin-bottom: 0; -} -dl { - margin: 0 1.625em; -} -dt { - font-weight: bold; -} -dd { - margin-bottom: 1.625em; -} -strong { - font-weight: bold; -} -cite, em, i { - font-style: italic; -} -blockquote { - font-family: Georgia, "Bitstream Charter", serif; - font-style: italic; - font-weight: normal; - margin: 0 3em; -} -blockquote em, blockquote i, blockquote cite { - font-style: normal; -} -blockquote cite { - color: #666; - font: 12px "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: 300; - letter-spacing: 0.05em; - text-transform: uppercase; -} -pre { - background: #f4f4f4; - font: 13px "Courier 10 Pitch", Courier, monospace; - line-height: 1.5; - margin-bottom: 1.625em; - overflow: auto; - padding: 0.75em 1.625em; -} -code, kbd { - font: 13px Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; -} -abbr, acronym, dfn { - border-bottom: 1px dotted #666; - cursor: help; -} -address { - display: block; - margin: 0 0 1.625em; -} -ins { - background: #fff9c0; - text-decoration: none; -} -sup, -sub { - font-size: 10px; - height: 0; - line-height: 1; - position: relative; - vertical-align: baseline; -} -sup { - bottom: 1ex; -} -sub { - top: .5ex; -} - -/* Forms */ -input[type=text], -input[type=password], -textarea { - background: #fafafa; - -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); - box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); - border: 1px solid #ddd; - color: #888; -} -input[type=text]:focus, -textarea:focus { - color: #373737; -} -textarea { - padding-left: 3px; - width: 98%; -} -input[type=text] { - padding: 3px; -} -input#s { - background: url(images/search.png) no-repeat 5px 6px; - -moz-border-radius: 2px; - border-radius: 2px; - font-size: 14px; - height: 22px; - line-height: 1.2em; - padding: 4px 10px 4px 28px; -} -input#searchsubmit { - display: none; -} - -/* Links */ -a { - color: #1982d1; - text-decoration: none; -} -a:focus, -a:active, -a:hover { - text-decoration: underline; -} - -/* Assistive text */ -.assistive-text { - position: absolute !important; - clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ - clip: rect(1px, 1px, 1px, 1px); -} -#access a.assistive-text:active, -#access a.assistive-text:focus { - background: #eee; - border-bottom: 1px solid #ddd; - color: #1982d1; - clip: auto !important; - font-size: 12px; - position: absolute; - text-decoration: underline; - top: 0; - left: 7.6%; -} - - -/* =Header ------------------------------------------------ */ - -#branding { - border-top: 2px solid #bbb; - padding-bottom: 10px; - position: relative; - z-index: 9999; -} -#site-title { - margin-right: 270px; - padding: 3.65625em 0 0; -} -#site-title a { - color: #111; - font-size: 30px; - font-weight: bold; - line-height: 36px; - text-decoration: none; -} -#site-title a:hover, -#site-title a:focus, -#site-title a:active { - color: #1982d1; -} -#site-description { - color: #7a7a7a; - font-size: 14px; - margin: 0 270px 3.65625em 0; -} -#branding img { - height: auto; - margin-bottom: -7px; - width: 100%; -} - - -/* =Menu --------------------------------------------------------------- */ - -#access { - background: #222; /* Show a solid color for older browsers */ - background: -moz-linear-gradient(#252525, #0a0a0a); - background: -o-linear-gradient(#252525, #0a0a0a); - background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#252525), to(#0a0a0a)); /* older webkit syntax */ - background: -webkit-linear-gradient(#252525, #0a0a0a); - -webkit-box-shadow: rgba(0, 0, 0, 0.4) 0px 1px 2px; - -moz-box-shadow: rgba(0, 0, 0, 0.4) 0px 1px 2px; - box-shadow: rgba(0, 0, 0, 0.4) 0px 1px 2px; - clear: both; - display: block; - float: left; - margin: 0 auto 6px; - width: 100%; -} -#access ul { - font-size: 13px; - list-style: none; - margin: 0 0 0 -0.8125em; - padding-left: 0; -} -#access li { - float: left; - position: relative; -} -#access a { - color: #eee; - display: block; - line-height: 3.333em; - padding: 0 1.2125em; - text-decoration: none; -} -#access ul ul { - -moz-box-shadow: 0 3px 3px rgba(0,0,0,0.2); - -webkit-box-shadow: 0 3px 3px rgba(0,0,0,0.2); - box-shadow: 0 3px 3px rgba(0,0,0,0.2); - display: none; - float: left; - margin: 0; - position: absolute; - top: 3.333em; - left: 0; - width: 188px; - z-index: 99999; -} -#access ul ul ul { - left: 100%; - top: 0; -} -#access ul ul a { - background: #f9f9f9; - border-bottom: 1px dotted #ddd; - color: #444; - font-size: 13px; - font-weight: normal; - height: auto; - line-height: 1.4em; - padding: 10px 10px; - width: 168px; -} -#access li:hover > a, -#access ul ul :hover > a, -#access a:focus { - background: #efefef; -} -#access li:hover > a, -#access a:focus { - background: #f9f9f9; /* Show a solid color for older browsers */ - background: -moz-linear-gradient(#f9f9f9, #e5e5e5); - background: -o-linear-gradient(#f9f9f9, #e5e5e5); - background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#f9f9f9), to(#e5e5e5)); /* Older webkit syntax */ - background: -webkit-linear-gradient(#f9f9f9, #e5e5e5); - color: #373737; -} -#access ul li:hover > ul { - display: block; -} -#access .current-menu-item > a, -#access .current-menu-ancestor > a, -#access .current_page_item > a, -#access .current_page_ancestor > a { - font-weight: bold; -} - -/* Search Form */ -#branding #searchform { - position: absolute; - top: 3.8em; - right: 7.6%; - text-align: right; -} -#branding #searchform div { - margin: 0; -} -#branding #s { - float: right; - -webkit-transition-duration: 400ms; - -webkit-transition-property: width, background; - -webkit-transition-timing-function: ease; - -moz-transition-duration: 400ms; - -moz-transition-property: width, background; - -moz-transition-timing-function: ease; - -o-transition-duration: 400ms; - -o-transition-property: width, background; - -o-transition-timing-function: ease; - width: 72px; -} -#branding #s:focus { - background-color: #f9f9f9; - width: 196px; -} -#branding #searchsubmit { - display: none; -} -#branding .only-search #searchform { - top: 5px; - z-index: 1; -} -#branding .only-search #s { - background-color: #666; - border-color: #000; - color: #222; -} -#branding .only-search #s, -#branding .only-search #s:focus { - width: 85%; -} -#branding .only-search #s:focus { - background-color: #bbb; -} -#branding .with-image #searchform { - top: auto; - bottom: -27px; - max-width: 195px; -} -#branding .only-search + #access div { - padding-right: 205px; -} - - -/* =Content ------------------------------------------------ */ - -#main { - clear: both; - padding: 1.625em 0 0; -} -.page-title { - color: #666; - font-size: 10px; - font-weight: 500; - letter-spacing: 0.1em; - line-height: 2.6em; - margin: 0 0 2.6em; - text-transform: uppercase; -} -.page-title a { - font-size: 12px; - font-weight: bold; - letter-spacing: 0; - text-transform: none; -} -.hentry, -.no-results { - border-bottom: 1px solid #ddd; - margin: 0 0 1.625em; - padding: 0 0 1.625em; - position: relative; -} -.hentry:last-child, -.no-results { - border-bottom: none; -} -.blog .sticky .entry-header .entry-meta { - clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ - clip: rect(1px, 1px, 1px, 1px); - position: absolute !important; -} -.entry-title, -.entry-header .entry-meta { - padding-right: 76px; -} -.entry-title { - clear: both; - color: #222; - font-size: 26px; - font-weight: bold; - line-height: 1.5em; - padding-bottom: .3em; - padding-top: 15px; -} -.entry-title, -.entry-title a { - color: #222; - text-decoration: none; -} -.entry-title a:hover, -.entry-title a:focus, -.entry-title a:active { - color: #1982d1; -} -.entry-meta { - color: #666; - clear: both; - font-size: 12px; - line-height: 18px; -} -.entry-meta a { - font-weight: bold; -} -.single-author .entry-meta .by-author { - display: none; -} -.entry-content, -.entry-summary { - padding: 1.625em 0 0; -} -.entry-content h1, -.entry-content h2, -.comment-content h1, -.comment-content h2 { - color: #000; - font-weight: bold; - margin: 0 0 .8125em; -} -.entry-content h3, -.comment-content h3 { - font-size: 10px; - letter-spacing: 0.1em; - line-height: 2.6em; - text-transform: uppercase; -} -.entry-content table, -.comment-content table { - border-bottom: 1px solid #ddd; - margin: 0 0 1.625em; - width: 100%; -} -.entry-content th, -.comment-content th { - color: #666; - font-size: 10px; - font-weight: 500; - letter-spacing: 0.1em; - line-height: 2.6em; - text-transform: uppercase; -} -.entry-content td, -.comment-content td { - border-top: 1px solid #ddd; - padding: 6px 10px 6px 0; -} -.entry-content #s { - width: 75%; -} -.comment-content ul, -.comment-content ol { - margin-bottom: 1.625em; -} -.comment-content ul ul, -.comment-content ol ol, -.comment-content ul ol, -.comment-content ol ul { - margin-bottom: 0; -} -dl.gallery-item { - margin: 0; -} -.page-link { - clear: both; - display: block; - margin: 0 0 1.625em; -} -.page-link a { - background: #eee; - color: #373737; - margin: 0; - padding: 2px 3px; - text-decoration: none; -} -.page-link a:hover { - background: #888; - color: #fff; - font-weight: bold; -} -.page-link span { - margin-right: 6px; -} -.entry-meta .edit-link a, -.commentlist .edit-link a { - background: #eee; - -moz-border-radius: 3px; - border-radius: 3px; - color: #666; - float: right; - font-size: 12px; - line-height: 1.5em; - font-weight: 300; - text-decoration: none; - padding: 0 8px; -} -.entry-meta .edit-link a:hover, -.commentlist .edit-link a:hover { - background: #888; - color: #fff; -} -.entry-content .edit-link { - clear: both; - display: block; -} - -/* Images */ -.entry-content img, -.comment-content img, -.widget img { - max-width: 97.5%; /* Fluid images for posts, comments, and widgets */ -} -img[class*="align"], -img[class*="wp-image-"], -img[class*="attachment-"] { - height: auto; /* Make sure images with WordPress-added height and width attributes are scaled correctly */ -} -img.size-full, -img.size-large { - max-width: 97.5%; - width: auto; /* Prevent stretching of full-size and large-size images with height and width attributes in IE8 */ - height: auto; /* Make sure images with WordPress-added height and width attributes are scaled correctly */ -} -.entry-content img.wp-smiley { - border: none; - margin-bottom: 0; - margin-top: 0; - padding: 0; -} -img.alignleft, -img.alignright, -img.aligncenter { - margin-bottom: 1.625em; -} -p img, -.wp-caption { - margin-top: 0.4em; -} -.wp-caption { - background: #eee; - margin-bottom: 1.625em; - max-width: 96%; - padding: 9px; -} -.wp-caption img { - display: block; - margin: 0 auto; - max-width: 98%; -} -.wp-caption .wp-caption-text, -.gallery-caption { - color: #666; - font-family: Georgia, serif; - font-size: 12px; -} -.wp-caption .wp-caption-text { - margin-bottom: 0.6em; - padding: 10px 0 5px 40px; - position: relative; -} -.wp-caption .wp-caption-text:before { - color: #666; - content: '\2014'; - font-size: 14px; - font-style: normal; - font-weight: bold; - margin-right: 5px; - position: absolute; - left: 10px; - top: 7px; -} -#content .gallery { - margin: 0 auto 1.625em; -} -#content .gallery a img { - border: none; -} -img#wpstats { - display: block; - margin: 0 auto 1.625em; -} -#content .gallery-columns-4 .gallery-item { - width: 23%; - padding-right: 2%; -} -#content .gallery-columns-4 .gallery-item img { - width: 100%; - height: auto; -} - -/* Image borders */ -img[class*="align"], -img[class*="wp-image-"], -#content .gallery .gallery-icon img {/* Add fancy borders to all WordPress-added images but not things like badges and icons and the like */ - border: 1px solid #ddd; - padding: 6px; -} -.wp-caption img { - border-color: #eee; -} -a:focus img[class*="align"], -a:hover img[class*="align"], -a:active img[class*="align"], -a:focus img[class*="wp-image-"], -a:hover img[class*="wp-image-"], -a:active img[class*="wp-image-"], -#content .gallery .gallery-icon a:focus img, -#content .gallery .gallery-icon a:hover img, -#content .gallery .gallery-icon a:active img {/* Add some useful style to those fancy borders for linked images ... */ - background: #eee; - border-color: #bbb; -} -.wp-caption a:focus img, -.wp-caption a:active img, -.wp-caption a:hover img {/* ... including captioned images! */ - background: #fff; - border-color: #ddd; -} - -/* Make sure embeds and iframes fit their containers */ -embed, -iframe, -object { - max-width: 100%; -} - -/* Password Protected Posts */ -.post-password-required .entry-header .comments-link { - margin: 1.625em 0 0; -} -.post-password-required input[type=password] { - margin: 0.8125em 0; -} -.post-password-required input[type=password]:focus { - background: #f7f7f7; -} - -/* Author Info */ -#author-info { - font-size: 12px; - overflow: hidden; -} -.singular #author-info { - background: #f9f9f9; - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 2.2em -35.6% 0 -35.4%; - padding: 20px 35.4%; -} -.archive #author-info { - border-bottom: 1px solid #ddd; - margin: 0 0 2.2em; - padding: 0 0 2.2em; -} -#author-avatar { - float: left; - margin-right: -78px; -} -#author-avatar img { - background: #fff; - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0 1px 2px #bbb; - -moz-box-shadow: 0 1px 2px #bbb; - box-shadow: 0 1px 2px #bbb; - padding: 3px; -} -#author-description { - float: left; - margin-left: 108px; -} -#author-description h2 { - color: #000; - font-size: 15px; - font-weight: bold; - margin: 5px 0 10px; -} - -/* Comments link */ -.entry-header .comments-link a { - background: #eee url(images/comment-bubble.png) no-repeat; - color: #666; - font-size: 13px; - font-weight: normal; - line-height: 35px; - overflow: hidden; - padding: 0 0 0; - position: absolute; - top: 1.5em; - right: 0; - text-align: center; - text-decoration: none; - width: 43px; - height: 36px; -} -.entry-header .comments-link a:hover, -.entry-header .comments-link a:focus, -.entry-header .comments-link a:active { - background-color: #1982d1; - color: #fff; - color: rgba(255,255,255,0.8); -} -.entry-header .comments-link .leave-reply { - visibility: hidden; -} - -/* -Post Formats Headings -To hide the headings, display: none the ".entry-header .entry-format" selector, -and remove the padding rules below. -*/ -.entry-header .entry-format { - color: #666; - font-size: 10px; - font-weight: 500; - letter-spacing: 0.1em; - line-height: 2.6em; - position: absolute; - text-transform: uppercase; - top: -5px; -} -.entry-header hgroup .entry-title { - padding-top: 15px; -} -article.format-aside .entry-content, -article.format-link .entry-content, -article.format-status .entry-content { - padding: 20px 0 0; -} -article.format-status .entry-content { - min-height: 65px; -} -.recent-posts .entry-header .entry-format { - display: none; -} -.recent-posts .entry-header hgroup .entry-title { - padding-top: 0; -} - -/* Singular content styles for Posts and Pages */ -.singular .hentry { - border-bottom: none; - padding: 4.875em 0 0; - position: relative; -} -.singular.page .hentry { - padding: 3.5em 0 0; -} -.singular .entry-title { - color: #000; - font-size: 36px; - font-weight: bold; - line-height: 48px; -} -.singular .entry-title, -.singular .entry-header .entry-meta { - padding-right: 0; -} -.singular .entry-header .entry-meta { - position: absolute; - top: 0; - left: 0; -} -blockquote.pull { - font-size: 21px; - font-weight: bold; - line-height: 1.6125em; - margin: 0 0 1.625em; - text-align: center; -} -.singular blockquote.pull { - margin: 0 -22.25% 1.625em; -} -.pull.alignleft { - margin: 0 1.625em 0 0; - text-align: right; - width: 33%; -} -.singular .pull.alignleft { - margin: 0 1.625em 0 -22.25%; -} -.pull.alignright { - margin: 0 0 0 1.625em; - text-align: left; - width: 33%; -} -.singular .pull.alignright { - margin: 0 -22.25% 0 1.625em; -} -.singular blockquote.pull.alignleft, -.singular blockquote.pull.alignright { - width: 33%; -} -.singular .entry-meta .edit-link a { - bottom: auto; - left: 50px; - position: absolute; - right: auto; - top: 80px; -} - - -/* =Aside ------------------------------------------------ */ - -.format-aside .entry-title, -.format-aside .entry-header .comments-link { - display: none; -} -.singular .format-aside .entry-title { - display: block; -} -.format-aside .entry-content { - padding: 0; -} -.singular .format-aside .entry-content { - padding: 1.625em 0 0; -} - - -/* =Link ------------------------------------------------ */ - -.format-link .entry-title, -.format-link .entry-header .comments-link { - display: none; -} -.singular .format-link .entry-title { - display: block; -} -.format-link .entry-content { - padding: 0; -} -.singular .format-link .entry-content { - padding: 1.625em 0 0; -} - - -/* =Gallery ------------------------------------------------ */ - -.format-gallery .gallery-thumb { - float: left; - display: block; - margin: .375em 1.625em 0 0; -} - - -/* =Status ------------------------------------------------ */ - -.format-status .entry-title, -.format-status .entry-header .comments-link { - display: none; -} -.singular .format-status .entry-title { - display: block; -} -.format-status .entry-content { - padding: 0; -} -.singular .format-status .entry-content { - padding: 1.625em 0 0; -} -.format-status img.avatar { - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0 1px 2px #ccc; - -moz-box-shadow: 0 1px 2px #ccc; - box-shadow: 0 1px 2px #ccc; - float: left; - margin: 4px 10px 2px 0; - padding: 0; -} - - -/* =Quote ------------------------------------------------ */ - -.format-quote blockquote { - color: #555; - font-size: 17px; - margin: 0; -} - - -/* =Image ------------------------------------------------ */ - -.indexed.format-image .entry-header { - min-height: 61px; /* Prevent the comment icon from colliding with the image when there is no title */ -} -.indexed.format-image .entry-content { - padding-top: 0.5em; -} -.indexed.format-image p, -.indexed.format-image p img { - margin-bottom: 0; -} -.indexed.format-image footer.entry-meta { - background: #ddd; - margin-top: -7px; - padding: 20px 30px; - overflow: hidden; -} -.indexed.format-image div.entry-meta { - display: inline-block; - float: left; - width: 35%; -} -.indexed.format-image div.entry-meta + div.entry-meta { - float: none; - width: 65%; -} -.indexed.format-image .entry-meta span.cat-links, -.indexed.format-image .entry-meta span.tag-links, -.indexed.format-image .entry-meta span.comments-link { - display: block; -} -.indexed.format-image footer.entry-meta a { - color: #444; -} -.indexed.format-image footer.entry-meta a:hover { - color: #fff; -} -#content .indexed.format-image img { - border: none; - max-width: 100%; - padding: 0; -} -.indexed.format-image .wp-caption { - background: #111; - margin-bottom: 0; - max-width: 96%; - padding: 11px; -} -.indexed.format-image .wp-caption .wp-caption-text { - color: #ddd; -} -.indexed.format-image .wp-caption .wp-caption-text:before { - color: #444; -} -.indexed.format-image a:hover img { - opacity: 0.8; -} - - -/* =error404 ------------------------------------------------ */ - -.error404 #main #searchform { - background: #f9f9f9; - border: 1px solid #ddd; - border-width: 1px 0; - margin: 0 -8.9% 1.625em; - overflow: hidden; - padding: 1.625em 8.9%; -} -.error404 #main #s { - width: 95%; -} -.error404 #main .widget { - clear: none; - float: left; - margin-right: 3.7%; - width: 30.85%; -} -.error404 #main .widget_archive { - margin-right: 0; -} -.error404 #main .widget_tag_cloud { - float: none; - margin-right: 0; - width: 100%; -} -.error404 .widgettitle { - font-size: 10px; - letter-spacing: 0.1em; - line-height: 2.6em; - text-transform: uppercase; -} - - -/* =Showcase ------------------------------------------------ */ - -h1.showcase-heading { - color: #666; - font-size: 10px; - font-weight: 500; - letter-spacing: 0.1em; - line-height: 2.6em; - text-transform: uppercase; -} - -/* Intro */ -article.intro { - background: #f9f9f9; - border-bottom: none; - margin: -1.855em -8.9% 1.625em; - padding: 0 8.9%; -} -article.intro .entry-title { - display: none; -} -article.intro .entry-content { - color: #111; - font-size: 16px; - padding: 1.625em 0 0.625em; -} -article.intro .edit-link a { - background: #aaa; - -moz-border-radius: 3px; - border-radius: 3px; - color: #fff; - font-size: 12px; - padding: 0 8px; - position: absolute; - top: 30px; - right: 20px; - text-decoration: none; -} -article.intro .edit-link a:hover, -article.intro .edit-link a:focus, -article.intro .edit-link a:active { - background: #777; -} - -/* Featured post */ -section.featured-post { - float: left; - margin: -1.625em -8.9% 1.625em; - padding: 1.625em 8.9% 0; - position: relative; - width: 100%; -} -section.featured-post .hentry { - border: none; - color: #666; - margin: 0; -} -section.featured-post .entry-meta { - clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ - clip: rect(1px, 1px, 1px, 1px); - position: absolute !important; -} - -/* Small featured post */ -section.featured-post .attachment-small-feature { - float: right; - height: auto; - margin: 0 -8.9% 1.625em 0; - max-width: 59%; - position: relative; - right: -15px; -} -section.featured-post.small { - padding-top: 0; -} -section.featured-post .attachment-small-feature:hover, -section.featured-post .attachment-small-feature:focus, -section.featured-post .attachment-small-feature:active { - opacity: .8; -} -article.feature-image.small { - float: left; - margin: 0 0 1.625em; - width: 45%; -} -article.feature-image.small .entry-title { - line-height: 1.2em; -} -article.feature-image.small .entry-summary { - color: #555; - font-size: 13px; -} -article.feature-image.small .entry-summary p a { - background: #222; - color: #eee; - display: block; - left: -23.8%; - padding: 9px 26px 9px 85px; - position: relative; - text-decoration: none; - top: 20px; - width: 180px; - z-index: 1; -} -article.feature-image.small .entry-summary p a:hover { - background: #1982d1; - color: #eee; - color: rgba(255,255,255,0.8); -} - -/* Large featured post */ -section.feature-image.large { - border: none; - max-height: 288px; - padding: 0; - width: 100%; -} -section.feature-image.large .showcase-heading { - display: none; -} -section.feature-image.large .hentry { - border-bottom: none; - left: 9%; - margin: 1.625em 9% 0 0; - position: absolute; - top: 0; -} -article.feature-image.large .entry-title a { - background: #222; - background: rgba(0,0,0,0.8); - -moz-border-radius: 3px; - border-radius: 3px; - color: #fff; - display: inline-block; - font-weight: 300; - padding: .2em 20px; -} -section.feature-image.large:hover .entry-title a, -section.feature-image.large .entry-title:hover a { - background: #eee; - background: rgba(255,255,255,0.8); - color: #222; -} -article.feature-image.large .entry-summary { - display: none; -} -section.feature-image.large img { - display: block; - height: auto; - max-width: 117.9%; - padding: 0 0 6px; -} - -/* Featured Slider */ -.featured-posts { - border-bottom: 1px solid #ddd; - display: block; - height: 328px; - margin: 1.625em -8.9% 20px; - max-width: 1000px; - padding: 0; - position: relative; - overflow: hidden; -} -.featured-posts .showcase-heading { - padding-left: 8.9%; -} -.featured-posts section.featured-post { - background: #fff; - height: 288px; - left: 0; - margin: 0; - position: absolute; - top: 30px; - width: auto; -} -.featured-posts section.featured-post.large { - max-width: 100%; - overflow: hidden; -} -.featured-posts section.featured-post { - -webkit-transition-duration: 200ms; - -webkit-transition-property: opacity, visibility; - -webkit-transition-timing-function: ease; - -moz-transition-duration: 200ms; - -moz-transition-property: opacity, visibility; - -moz-transition-timing-function: ease; -} -.featured-posts section.featured-post { - opacity: 0; - visibility: hidden; -} -.featured-posts #featured-post-1 { - opacity: 1; - visibility: visible; -} -.featured-post .feature-text:after, -.featured-post .feature-image.small:after { - content: ' '; - background: -moz-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,0)), color-stop(100%,rgba(255,255,255,1))); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#ffffff',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* W3C */ - width: 100%; - height: 45px; - position: absolute; - top: 230px; -} -.featured-post .feature-image.small:after { - top: 253px; -} -#content .feature-slider { - top: 5px; - right: 8.9%; - overflow: visible; - position: absolute; -} -.feature-slider ul { - list-style-type: none; - margin: 0; -} -.feature-slider li { - float: left; - margin: 0 6px; -} -.feature-slider a { - background: #3c3c3c; - background: rgba(60,60,60,0.9); - -moz-border-radius: 12px; - border-radius: 12px; - -webkit-box-shadow: inset 1px 1px 5px rgba(0,0,0,0.5), inset 0 0 2px rgba(255,255,255,0.5); - -moz-box-shadow: inset 1px 1px 5px rgba(0,0,0,0.5), inset 0 0 2px rgba(255,255,255,0.5); - box-shadow: inset 1px 1px 5px rgba(0,0,0,0.5), inset 0 0 2px rgba(255,255,255,0.5); - display: block; - width: 14px; - height: 14px; -} -.feature-slider a.active { - background: #1982d1; - -webkit-box-shadow: inset 1px 1px 5px rgba(0,0,0,0.4), inset 0 0 2px rgba(255,255,255,0.8); - -moz-box-shadow: inset 1px 1px 5px rgba(0,0,0,0.4), inset 0 0 2px rgba(255,255,255,0.8); - box-shadow: inset 1px 1px 5px rgba(0,0,0,0.4), inset 0 0 2px rgba(255,255,255,0.8); - cursor: default; - opacity: 0.5; -} - -/* Recent Posts */ -section.recent-posts { - padding: 0 0 1.625em; -} -section.recent-posts .hentry { - border: none; - margin: 0; -} -section.recent-posts .other-recent-posts { - border-bottom: 1px solid #ddd; - list-style: none; - margin: 0; -} -section.recent-posts .other-recent-posts li { - padding: 0.3125em 0; - position: relative; -} -section.recent-posts .other-recent-posts .entry-title { - border-top: 1px solid #ddd; - font-size: 17px; -} -section.recent-posts .other-recent-posts a[rel="bookmark"] { - color: #373737; - float: left; - max-width: 84%; -} -section.recent-posts .other-recent-posts a[rel="bookmark"]:after { - content: '-'; - color: transparent; - font-size: 11px; -} -section.recent-posts .other-recent-posts a[rel="bookmark"]:hover { -} -section.recent-posts .other-recent-posts .comments-link a, -section.recent-posts .other-recent-posts .comments-link > span { - border-bottom: 2px solid #999; - bottom: -2px; - color: #444; - display: block; - font-size: 10px; - font-weight: 500; - line-height: 2.76333em; - padding: 0.3125em 0 0.3125em 1em; - position: absolute; - right: 0; - text-align: right; - text-transform: uppercase; - z-index: 1; -} -section.recent-posts .other-recent-posts .comments-link > span { - border-color: #bbb; - color: #888; -} -section.recent-posts .other-recent-posts .comments-link a:hover { - color: #1982d1; - border-color: #1982d1; -} -section.recent-posts .other-recent-posts li:after { - clear: both; - content: '.'; - display: block; - height: 0; - visibility: hidden; -} - - -/* =Attachments ------------------------------------------------ */ - -.image-attachment div.attachment { - background: #f9f9f9; - border: 1px solid #ddd; - border-width: 1px 0; - margin: 0 -8.9% 1.625em; - overflow: hidden; - padding: 1.625em 1.625em 0; - text-align: center; -} -.image-attachment div.attachment img { - display: block; - height: auto; - margin: 0 auto 1.625em; - max-width: 100%; -} -.image-attachment div.attachment a img { - border-color: #f9f9f9; -} -.image-attachment div.attachment a:focus img, -.image-attachment div.attachment a:hover img, -.image-attachment div.attachment a:active img { - border-color: #ddd; - background: #fff; -} -.image-attachment .entry-caption p { - font-size: 10px; - letter-spacing: 0.1em; - line-height: 2.6em; - margin: 0 0 2.6em; - text-transform: uppercase; -} - - -/* =Navigation --------------------------------------------------------------- */ - -#content nav { - clear: both; - overflow: hidden; - padding: 0 0 1.625em; -} -#content nav a { - font-size: 12px; - font-weight: bold; - line-height: 2.2em; -} -#nav-above { - padding: 0 0 1.625em; -} -#nav-above { - display: none; -} -.paged #nav-above { - display: block; -} -.nav-previous { - float: left; - width: 50%; -} -.nav-next { - float: right; - text-align: right; - width: 50%; -} -#content nav .meta-nav { - font-weight: normal; -} - -/* Singular navigation */ -#nav-single { - float: right; - position: relative; - top: -0.3em; - text-align: right; - z-index: 1; -} -#nav-single .nav-previous, -#nav-single .nav-next { - float: none; - width: auto; -} -#nav-single .nav-next { - padding-left: .5em; -} - - -/* =Widgets ------------------------------------------------ */ - -.widget-area { - font-size: 12px; -} -.widget { - clear: both; - margin: 0 0 2.2em; -} -.widget-title { - color: #666; - font-size: 10px; - font-weight: 500; - letter-spacing: 0.1em; - line-height: 2.6em; - text-transform: uppercase; -} -.widget ul { - font-size: 15px; - margin: 0; -} -.widget ul ul { - margin-left: 1.5em; -} -.widget ul li { - color: #777; - font-size: 13px; -} -.widget a { - font-weight: bold; - text-decoration: none; -} -.widget a:hover, -.widget a:focus, -.widget a:active { - text-decoration: underline; -} - -/* Search Widget */ -.widget_search form { - margin: 0 0 1.625em; -} -.widget_search #s { - width: 77%; -} -.widget_search #searchsubmit { - background: #ddd; - border: 1px solid #ccc; - -webkit-box-shadow: inset 0px -1px 1px rgba(0, 0, 0, 0.09); - -moz-box-shadow: inset 0px -1px 1px rgba(0, 0, 0, 0.09); - box-shadow: inset 0px -1px 1px rgba(0, 0, 0, 0.09); - color: #888; - font-size: 13px; - line-height: 25px; - position: relative; - top: -2px; -} -.widget_search #searchsubmit:active { - background: #1982d1; - border-color: #0861a5; - -webkit-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.1); - box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.1); - color: #bfddf3; -} - -/* Ephemera Widget */ -section.ephemera ol, -.widget_twentyeleven_ephemera ol { - list-style: square; - margin: 5px 0 0; -} -.widget_twentyeleven_ephemera .widget-entry-title { - font-size: 15px; - font-weight: bold; - padding: 0; -} -.widget_twentyeleven_ephemera .comments-link a, -.widget_twentyeleven_ephemera .comments-link > span { - color: #666; - display: block; - font-size: 10px; - font-weight: 500; - line-height: 2.76333em; - text-transform: uppercase; -} -section.ephemera .entry-title .comments-link a:hover, -.widget_twentyeleven_ephemera .entry-title .comments-link a:hover { -} -section.ephemera .entry-title a span { - color: #29628d; -} - -/* Twitter */ -.widget_twitter li { - list-style-type: none; - margin-bottom: 14px; -} -.widget_twitter .timesince { - display: block; - font-size: 11px; - margin-right: -10px; - text-align: right; -} - -/* Widget Image */ -.widget_image img { - height: auto; - max-width: 100%; -} - -/* Calendar Widget */ - -.widget_calendar #wp-calendar { - color: #555; - width: 95%; - text-align: center; -} -.widget_calendar #wp-calendar caption, -.widget_calendar #wp-calendar td, -.widget_calendar #wp-calendar th { - text-align: center; -} -.widget_calendar #wp-calendar caption { - font-size: 11px; - font-weight: 500; - padding: 5px 0 3px 0; - text-transform: uppercase; -} -.widget_calendar #wp-calendar th { - background: #f4f4f4; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; - font-weight: bold; -} -.widget_calendar #wp-calendar tfoot td { - background: #f4f4f4; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; -} - - -/* =Comments ------------------------------------------------ */ - -#comments-title { - color: #666; - font-size: 10px; - font-weight: 500; - line-height: 2.6em; - padding: 0 0 2.6em; - text-transform: uppercase; -} -.nopassword, -.nocomments { - color: #aaa; - font-size: 24px; - font-weight: 100; - margin: 26px 0; - text-align: center; -} -.commentlist { - list-style: none; - margin: 0 auto; - width: 68.9%; -} -.content .commentlist, -.page-template-sidebar-page-php .commentlist { - width: 100%; /* reset the width for the one-column and sidebar page layout */ -} -.commentlist > li.comment { - background: #f6f6f6; - border: 1px solid #ddd; - -moz-border-radius: 3px; - border-radius: 3px; - margin: 0 0 1.625em; - padding: 1.625em; - position: relative; -} -.commentlist .pingback { - margin: 0 0 1.625em; - padding: 0 1.625em; -} -.commentlist .children { - list-style: none; - margin: 0; -} -.commentlist .children li.comment { - background: #fff; - border-left: 1px solid #ddd; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; - margin: 1.625em 0 0; - padding: 1.625em; - position: relative; -} -.commentlist .children li.comment .fn { - display: block; -} -.comment-meta .fn { - font-style: normal; -} -.comment-meta { - color: #666; - font-size: 12px; - line-height: 2.2em; -} -.commentlist .children li.comment .comment-meta { - line-height: 1.625em; - margin-left: 50px; -} -.commentlist .children li.comment .comment-content { - margin: 1.625em 0 0; -} -.comment-meta a { - font-weight: bold; -} -.comment-meta a:focus, -.comment-meta a:active, -.comment-meta a:hover { -} -.commentlist .avatar { - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0 1px 2px #ccc; - -moz-box-shadow: 0 1px 2px #ccc; - box-shadow: 0 1px 2px #ccc; - left: -102px; - padding: 0; - position: absolute; - top: 0; -} -.commentlist > li:before { - content: url(images/comment-arrow.png); - left: -21px; - position: absolute; -} -.commentlist > li.pingback:before { - content: ''; -} -.commentlist .children .avatar { - background: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - left: 2.2em; - padding: 0; - top: 2.2em; -} -a.comment-reply-link { - background: #eee; - -moz-border-radius: 3px; - border-radius: 3px; - color: #666; - display: inline-block; - font-size: 12px; - padding: 0 8px; - text-decoration: none; -} -a.comment-reply-link:hover, -a.comment-reply-link:focus, -a.comment-reply-link:active { - background: #888; - color: #fff; -} -a.comment-reply-link > span { - display: inline-block; - position: relative; - top: -1px; -} - -/* Post author highlighting */ -.commentlist > li.bypostauthor { - background: #ddd; - border-color: #d3d3d3; -} -.commentlist > li.bypostauthor .comment-meta { - color: #575757; -} -.commentlist > li.bypostauthor .comment-meta a:focus, -.commentlist > li.bypostauthor .comment-meta a:active, -.commentlist > li.bypostauthor .comment-meta a:hover { -} -.commentlist > li.bypostauthor:before { - content: url(images/comment-arrow-bypostauthor.png); -} - -/* Post Author threaded comments */ -.commentlist .children > li.bypostauthor { - background: #ddd; - border-color: #d3d3d3; -} - -/* sidebar-page.php comments */ -/* Make sure we have room for our comment avatars */ -.page-template-sidebar-page-php .commentlist > li.comment, -.page-template-sidebar-page-php.commentlist .pingback { - margin-left: 102px; - width: auto; -} -/* And a full-width comment form */ -.page-template-sidebar-page-php #respond { - width: auto; -} - -/* Comment Form */ -#respond { - background: #ddd; - border: 1px solid #d3d3d3; - -moz-border-radius: 3px; - border-radius: 3px; - margin: 0 auto 1.625em; - padding: 1.625em; - position: relative; - width: 68.9%; -} -#respond input[type="text"], -#respond textarea { - background: #fff; - border: 4px solid #eee; - -moz-border-radius: 5px; - border-radius: 5px; - -webkit-box-shadow: inset 0 1px 3px rgba(204,204,204,0.95); - -moz-box-shadow: inset 0 1px 3px rgba(204,204,204,0.95); - box-shadow: inset 0 1px 3px rgba(204,204,204,0.95); - position: relative; - padding: 10px; - text-indent: 80px; -} -#respond .comment-form-author, -#respond .comment-form-email, -#respond .comment-form-url, -#respond .comment-form-comment { - position: relative; -} -#respond .comment-form-author label, -#respond .comment-form-email label, -#respond .comment-form-url label, -#respond .comment-form-comment label { - background: #eee; - -webkit-box-shadow: 1px 2px 2px rgba(204,204,204,0.8); - -moz-box-shadow: 1px 2px 2px rgba(204,204,204,0.8); - box-shadow: 1px 2px 2px rgba(204,204,204,0.8); - color: #555; - display: inline-block; - font-size: 13px; - left: 4px; - min-width: 60px; - padding: 4px 10px; - position: relative; - top: 40px; - z-index: 1; -} -#respond input[type="text"]:focus, -#respond textarea:focus { - text-indent: 0; - z-index: 1; -} -#respond textarea { - resize: vertical; - width: 95%; -} -#respond .comment-form-author .required, -#respond .comment-form-email .required { - color: #bd3500; - font-size: 22px; - font-weight: bold; - left: 75%; - position: absolute; - top: 45px; - z-index: 1; -} -#respond .comment-notes, -#respond .logged-in-as { - font-size: 13px; -} -#respond p { - margin: 10px 0; -} -#respond .form-submit { - float: right; - margin: -20px 0 10px; -} -#respond input#submit { - background: #222; - border: none; - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0px 1px 2px rgba(0,0,0,0.3); - -moz-box-shadow: 0px 1px 2px rgba(0,0,0,0.3); - box-shadow: 0px 1px 2px rgba(0,0,0,0.3); - color: #eee; - cursor: pointer; - font-size: 15px; - margin: 20px 0; - padding: 5px 42px 5px 22px; - position: relative; - left: 30px; - text-shadow: 0 -1px 0 rgba(0,0,0,0.3); -} -#respond input#submit:active { - background: #1982d1; - color: #bfddf3; -} -#respond #cancel-comment-reply-link { - color: #666; - margin-left: 10px; - text-decoration: none; -} -#respond .logged-in-as a:hover, -#respond #cancel-comment-reply-link:hover { - text-decoration: underline; -} -.commentlist #respond { - margin: 1.625em 0 0; - width: auto; -} -#reply-title { - color: #373737; - font-size: 24px; - font-weight: bold; - line-height: 30px; -} -#cancel-comment-reply-link { - color: #888; - display: block; - font-size: 10px; - font-weight: normal; - line-height: 2.2em; - letter-spacing: 0.05em; - position: absolute; - right: 1.625em; - text-decoration: none; - text-transform: uppercase; - top: 1.1em; -} -#cancel-comment-reply-link:focus, -#cancel-comment-reply-link:active, -#cancel-comment-reply-link:hover { - color: #ff4b33; -} -#respond label { - line-height: 2.2em; -} -#respond input[type=text] { - display: block; - height: 24px; - width: 75%; -} -#respond p { - font-size: 12px; -} -p.comment-form-comment { - margin: 0; -} -.form-allowed-tags { - display: none; -} - - -/* =Footer ------------------------------------------------ */ - -#colophon { - clear: both; -} -#supplementary { - border-top: 1px solid #ddd; - padding: 1.625em 7.6%; - overflow: hidden; -} - -/* Two Footer Widget Areas */ -#supplementary.two .widget-area { - float: left; - margin-right: 3.7%; - width: 48.1%; -} -#supplementary.two .widget-area + .widget-area { - margin-right: 0; -} - -/* Three Footer Widget Areas */ -#supplementary.three .widget-area { - float: left; - margin-right: 3.7%; - width: 30.85%; -} -#supplementary.three .widget-area + .widget-area + .widget-area { - margin-right: 0; -} - -/* Site Generator Line */ -#site-generator { - background: #f9f9f9; - border-top: 1px solid #ddd; - color: #666; - font-size: 12px; - line-height: 2.2em; - padding: 2.2em 0.5em; - text-align: center; -} -#site-generator a { - color: #555; - font-weight: bold; -} -#site-generator .sep { - background: url(images/wordpress.png) center left no-repeat; - color: transparent; - display: inline-block; - height: 16px; - line-height: 16px; - margin: 0 7px; - width: 16px; -} - - -/* =Responsive Structure ------------------------------------------------ */ - -@media (max-width: 800px) { - /* Simplify the basic layout */ - #main #content { - margin: 0 7.6%; - width: auto; - } - #nav-below { - border-bottom: 1px solid #ddd; - margin-bottom: 1.625em; - } - #main #secondary { - float: none; - margin: 0 7.6%; - width: auto; - } - /* Simplify the showcase template */ - .page-template-showcase-php .featured-posts { - min-height: 280px; - } - .featured-posts section.featured-post { - height: auto; - } - .page-template-showcase-php section.recent-posts { - float: none; - margin: 0; - width: 100%; - } - .page-template-showcase-php #main .widget-area { - float: none; - margin: 0; - width: auto; - } - .page-template-showcase-php .other-recent-posts { - border-bottom: 1px solid #ddd; - } - /* Simplify the showcase template when small feature */ - section.featured-post .attachment-small-feature, - .one-column section.featured-post .attachment-small-feature { - border: none; - display: block; - float: left; - height: auto; - margin: 0.625em auto 1.025em; - max-width: 30%; - position: static; - } - article.feature-image.small { - float: right; - margin: 0 0 1.625em; - width: 64%; - } - .one-column article.feature-image.small .entry-summary { - height: auto; - } - article.feature-image.small .entry-summary p a { - left: 0; - padding-left: 20px; - padding-right: 20px; - width: auto; - } - /* Remove the margin on singular articles */ - .singular .entry-header, - .singular .entry-content, - .singular footer.entry-meta, - .singular #comments-title { - width: 100%; - } - /* Simplify the pullquotes and pull styles */ - .singular blockquote.pull { - margin: 0 0 1.625em; - } - .singular .pull.alignleft { - margin: 0 1.625em 0 0; - } - .singular .pull.alignright { - margin: 0 0 0 1.625em; - } - .singular .entry-meta .edit-link a { - left: 0; - position: absolute; - top: 40px; - } - .singular #author-info { - margin: 2.2em -8.8% 0; - padding: 20px 8.8%; - } - /* Make sure we have room for our comment avatars */ - .commentlist { - width: 100%; - } - .commentlist > li.comment, - .commentlist .pingback { - margin-left: 102px; - width: auto; - } - /* And a full-width comment form */ - #respond { - width: auto; - } - /* No need to float footer widgets at this size */ - #colophon #supplementary .widget-area { - float: none; - margin-right: 0; - width: auto; - } - /* No need to float 404 widgets at this size */ - .error404 #main .widget { - float: none; - margin-right: 0; - width: auto; - } - -} -@media (max-width: 650px) { - /* @media (max-width: 650px) Reduce font-sizes for better readability on smaller devices */ - body, input, textarea { - font-size: 13px; - } - #site-title a { - font-size: 24px; - } - #site-description { - font-size: 12px; - } - #access ul { - font-size: 12px; - } - article.intro .entry-content { - font-size: 12px; - } - .entry-title { - font-size: 21px; - } - .featured-post .entry-title { - font-size: 14px; - } - .singular .entry-title { - font-size: 28px; - } - .entry-meta { - font-size: 12px; - } - blockquote { - margin: 0; - } - blockquote.pull { - font-size: 17px; - } - /* Reposition the site title and description slightly */ - #site-title { - padding: 5.30625em 0 0; - } - #site-title, - #site-description { - margin-right: 0; - } - /* Make sure the logo and search form don't collide */ - #branding #searchform { - top: 1.625em !important; - } - /* Floated content doesn't work well at this size */ - .alignleft, - .alignright { - float: none; - margin-left: 0; - margin-right: 0; - } - /* Make sure the post-post navigation doesn't collide with anything */ - #nav-single { - display: block; - position: static; - } - .singular .hentry { - padding: 1.625em 0 0; - } - .singular.page .hentry { - padding: 1.625em 0 0; - } - /* Talking avatars take up too much room at this size */ - .commentlist > li.comment, - .commentlist > li.pingback { - margin-left: 0 !important; - } - .commentlist .avatar { - background: transparent; - display: block; - padding: 0; - position: static; - } - .commentlist .children .avatar { - background: none; - left: 2.2em; - padding: 0; - position: absolute; - top: 2.2em; - } - /* Use the available space in the smaller comment form */ - #respond input[type="text"] { - width: 95%; - } - #respond .comment-form-author .required, - #respond .comment-form-email .required { - left: 95%; - } - #content .gallery-columns-3 .gallery-item { - width: 31%; - padding-right: 2%; - } - #content .gallery-columns-3 .gallery-item img { - width: 100%; - height: auto; - } - -} -@media (max-width: 450px) { - #content .gallery-columns-2 .gallery-item { - width: 45%; - padding-right: 4%; - } - #content .gallery-columns-2 .gallery-item img { - width: 100%; - height: auto; - } - -} -@media only screen and (min-device-width: 320px) and (max-device-width: 480px) { - body { - padding: 0; - } - #page { - margin-top: 0; - } - #branding { - border-top: none; - } - -} - - -/* =Print ------------------------------------------------ */ - -@media print { - body { - background: none !important; - font-size: 10pt; - } - footer.entry-meta a[rel=bookmark]:link:after, - footer.entry-meta a[rel=bookmark]:visited:after { - content: " [" attr(href) "] "; /* Show URLs */ - } - #page { - clear: both !important; - display: block !important; - float: none !important; - max-width: 100%; - position: relative !important; - } - #branding { - border-top: none !important; - padding: 0; - } - #branding hgroup { - margin: 0; - } - #site-title a { - font-size: 21pt; - } - #site-description { - font-size: 10pt; - } - #branding #searchform { - display: none; - } - #branding img { - display: none; - } - #access { - display: none; - } - #main { - border-top: none; - box-shadow: none; - } - #primary { - float: left; - margin: 0; - width: 100%; - } - #content { - margin: 0; - width: auto; - } - .singular #content { - margin: 0; - width: 100%; - } - .singular .entry-header .entry-meta { - position: static; - } - .entry-meta .edit-link a { - display: none; - } - #content nav { - display: none; - } - .singular .entry-header, - .singular .entry-content, - .singular footer.entry-meta, - .singular #comments-title { - margin: 0; - width: 100%; - } - .singular .hentry { - padding: 0; - } - .entry-title, - .singular .entry-title { - font-size: 21pt; - } - .entry-meta { - font-size: 10pt; - } - .entry-header .comments-link { - display: none; - } - .page-link { - display: none; - } - .singular #author-info { - background: none; - border-bottom: none; - border-top: none; - margin: 2.2em 0 0; - padding: 0; - } - #respond { - display: none; - } - .widget-area { - display: none; - } - #colophon { - display: none; - } - - /* Comments */ - .commentlist > li.comment { - background: none; - border: 1px solid #ddd; - -moz-border-radius: 3px 3px 3px 3px; - border-radius: 3px 3px 3px 3px; - margin: 0 auto 1.625em; - padding: 1.625em; - position: relative; - width: auto; - } - .commentlist .avatar { - height: 39px; - left: 2.2em; - top: 2.2em; - width: 39px; - } - .commentlist li.comment .comment-meta { - line-height: 1.625em; - margin-left: 50px; - } - .commentlist li.comment .fn { - display: block; - } - .commentlist li.comment .comment-content { - margin: 1.625em 0 0; - } - .commentlist .comment-edit-link { - display: none; - } - .commentlist > li::before, - .commentlist > li.bypostauthor::before { - content: ''; - } - .commentlist .reply { - display: none; - } - - /* Post author highlighting */ - .commentlist > li.bypostauthor { - color: #444; - } - .commentlist > li.bypostauthor .comment-meta { - color: #666; - } - .commentlist > li.bypostauthor:before { - content: none; - } - - /* Post Author threaded comments */ - .commentlist .children > li.bypostauthor { - background: #fff; - border-color: #ddd; - } - .commentlist .children > li.bypostauthor > article, - .commentlist .children > li.bypostauthor > article .comment-meta { - color: #666; - } - -} - - -/* =IE7 ------------------------------------------------ */ - -#ie7 article.intro { - margin-left: -7.6%; - margin-right: -7.6%; - padding-left: -7.6%; - padding-right: -7.6%; - max-width: 1000px; -} -#ie7 section.featured-post { - margin-left: -7.6%; - margin-right: -7.6%; - max-width: 850px; -} -#ie7 section.recent-posts { - margin-right: 7.6%; -} diff --git a/spec/samples/common/models/wp_theme/vulnerable/themes_vulns.json b/spec/samples/common/models/wp_theme/vulnerable/themes_vulns.json deleted file mode 100644 index c123ae9f..00000000 --- a/spec/samples/common/models/wp_theme/vulnerable/themes_vulns.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "mr-smith": { - "vulnerabilities":[ - { - "id":2989, - "title":"I should not appear in the results", - "references": { - "url": ["Ref 1", "Ref 2"], - "osvdb": ["osvdb"], - "cve": ["2011-001"], - "secunia": ["secunia"], - "metasploit": ["exploit/ex1"], - "exploitdb": ["exploitdb"] - }, - "type":"XSS", - "fixed_in":"", - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - }, - { - "id":2989, - "title":"Neither do I", - "references": { - "url": ["Ref 1", "Ref 2"], - "osvdb": ["osvdb"], - "cve": ["2011-001"], - "secunia": ["secunia"], - "metasploit": ["exploit/ex1"], - "exploitdb": ["exploitdb"] - }, - "type":"XSS", - "fixed_in":"", - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - } - ] - }, - "the-oracle": { - "vulnerabilities":[ - { - "id":2993, - "title":"I see you", - "references": { - "url": ["Ref 1", "Ref 2"], - "osvdb": ["osvdb"], - "cve": ["2011-001"], - "secunia": ["secunia"], - "metasploit": ["exploit/ex1"], - "exploitdb": ["exploitdb"] - }, - "type":"FPD", - "fixed_in":"", - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - } - ] - } -} - diff --git a/spec/samples/common/models/wp_user/brute_forcable/wordlist-iso-8859-1.txt b/spec/samples/common/models/wp_user/brute_forcable/wordlist-iso-8859-1.txt deleted file mode 100644 index c97e18de..00000000 --- a/spec/samples/common/models/wp_user/brute_forcable/wordlist-iso-8859-1.txt +++ /dev/null @@ -1,7 +0,0 @@ -password1 -pa55w0rd -#not-a-comment -admin -root -kansei - spaceafterandbefore diff --git a/spec/samples/common/models/wp_user/brute_forcable/wordlist-utf-8.txt b/spec/samples/common/models/wp_user/brute_forcable/wordlist-utf-8.txt deleted file mode 100644 index 884766f4..00000000 --- a/spec/samples/common/models/wp_user/brute_forcable/wordlist-utf-8.txt +++ /dev/null @@ -1,7 +0,0 @@ -password1 -pa55w0rd -#not-a-coment -admin -root -kansei£Ô - spaceafterandbefore diff --git a/spec/samples/common/models/wp_user/existable/admin.html b/spec/samples/common/models/wp_user/existable/admin.html deleted file mode 100644 index c1ff496e..00000000 --- a/spec/samples/common/models/wp_user/existable/admin.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - admin d-name | Wordpress 3.3.2 - - - - - - - - - - - - - - - - - diff --git a/spec/samples/common/models/wp_user/existable/chinese_chars.html b/spec/samples/common/models/wp_user/existable/chinese_chars.html deleted file mode 100644 index 4fc916c0..00000000 --- a/spec/samples/common/models/wp_user/existable/chinese_chars.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - -一路疯下去 - - - - diff --git a/spec/samples/common/models/wp_version/findable/advanced_fingerprinting/3.2.1.js b/spec/samples/common/models/wp_version/findable/advanced_fingerprinting/3.2.1.js deleted file mode 100644 index c5bf4868..00000000 --- a/spec/samples/common/models/wp_version/findable/advanced_fingerprinting/3.2.1.js +++ /dev/null @@ -1 +0,0 @@ -var PubSub,fullscreen,wptitlehint;PubSub=function(){this.topics={}};PubSub.prototype.subscribe=function(a,b){if(!this.topics[a]){this.topics[a]=[]}this.topics[a].push(b);return b};PubSub.prototype.unsubscribe=function(b,e){var c,a,d=this.topics[b];if(!d){return e||[]}if(e){for(c=0,a=d.length;c120){return}}if(block){return}block=true;setTimeout(function(){block=false},400);if(a.timer){clearTimeout(a.timer)}else{e.publish(l)}function f(){e.publish(h);a.timer=0}a.timer=setTimeout(f,g)};b.on=function(){if(a.visible){return}a.mode=c("#"+a.editor_id).is(":hidden")?"tinymce":"html";if(!a.element){b.ui.init()}a.is_mce_on=a.has_tinymce&&typeof(tinyMCE.get(a.editor_id))!="undefined";b.ui.fade("show","showing","shown")};b.off=function(){if(!a.visible){return}b.ui.fade("hide","hiding","hidden")};b.switchmode=function(g){var f=a.mode;if(!g||!a.visible||!a.has_tinymce){return f}if(f==g){return f}e.publish("switchMode",[f,g]);a.mode=g;e.publish("switchedMode",[f,g]);return g};b.save=function(){var h=c("#hiddenaction"),f=h.val(),i=c("#wp-fullscreen-save img"),g=c("#wp-fullscreen-save span");i.show();b.savecontent();h.val("wp-fullscreen-save-post");c.post(ajaxurl,c("form#post").serialize(),function(j){i.hide();g.show();setTimeout(function(){g.fadeOut(1000)},3000);if(j.last_edited){c("#wp-fullscreen-save input").attr("title",j.last_edited)}},"json");h.val(f)};b.savecontent=function(){var f,g;c("#"+a.title_id).val(c("#wp-fullscreen-title").val());if(a.mode==="tinymce"&&(f=tinyMCE.get("wp_mce_fullscreen"))){g=f.save()}else{g=c("#wp_mce_fullscreen").val()}c("#"+a.editor_id).val(g);c(document).triggerHandler("wpcountwords",[g])};set_title_hint=function(f){if(!f.val().length){f.siblings("label").css("visibility","")}else{f.siblings("label").css("visibility","hidden")}};b.dfw_width=function(h){var g=c("#wp-fullscreen-wrap"),f=g.width();if(!h){g.width(c("#wp-fullscreen-central-toolbar").width());deleteUserSetting("dfw_width");return}f=h+f;if(f<200||f>1200){return}g.width(f);setUserSetting("dfw_width",f)};e.subscribe("showToolbar",function(){a.toolbars.removeClass("fade-1000").addClass("fade-300");b.fade.In(a.toolbars,300,function(){e.publish("toolbarShown")},true);c("#wp-fullscreen-body").addClass("wp-fullscreen-focus");a.toolbar_shown=true});e.subscribe("hideToolbar",function(){a.toolbars.removeClass("fade-300").addClass("fade-1000");b.fade.Out(a.toolbars,1000,function(){e.publish("toolbarHidden")},true);c("#wp-fullscreen-body").removeClass("wp-fullscreen-focus")});e.subscribe("toolbarShown",function(){a.toolbars.removeClass("fade-300")});e.subscribe("toolbarHidden",function(){a.toolbars.removeClass("fade-1000");a.toolbar_shown=false});e.subscribe("show",function(){var f=c("#wp-fullscreen-title").val(c("#"+a.title_id).val());set_title_hint(f);c("#wp-fullscreen-save input").attr("title",c("#last-edit").text());a.textarea_obj.value=edCanvas.value;if(a.has_tinymce&&a.mode==="tinymce"){tinyMCE.execCommand("wpFullScreenInit")}a._edCanvas=edCanvas;edCanvas=a.textarea_obj;a.orig_y=c(window).scrollTop()});e.subscribe("showing",function(){c(document.body).addClass("fullscreen-active");b.refresh_buttons();c(document).bind("mousemove.fullscreen",function(f){d("showToolbar","hideToolbar",2000,f)});d("showToolbar","hideToolbar",2000);b.bind_resize();setTimeout(b.resize_textarea,200);scrollTo(0,0);c("#wpadminbar").hide()});e.subscribe("shown",function(){a.visible=true;if(a.has_tinymce&&!a.is_mce_on){htmled=document.getElementById(a.editor_id),old_val=htmled.value;htmled.value=switchEditors.wpautop(old_val);tinyMCE.settings.setup=function(f){f.onInit.add(function(g){g.hide();delete tinyMCE.settings.setup;g.getElement().value=old_val})};tinyMCE.execCommand("mceAddControl",false,a.editor_id);a.is_mce_on=true}});e.subscribe("hide",function(){if(a.has_tinymce&&a.mode==="tinymce"&&c("#"+a.editor_id).is(":visible")){switchEditors.go(a.editor_id,"tinymce")}else{if(a.mode==="html"&&c("#"+a.editor_id).is(":hidden")){switchEditors.go(a.editor_id,"html")}}b.savecontent();c(document).unbind(".fullscreen");c(a.textarea_obj).unbind(".grow");if(a.has_tinymce&&a.mode==="tinymce"){tinyMCE.execCommand("wpFullScreenSave")}set_title_hint(c("#"+a.title_id));edCanvas=a._edCanvas;edCanvas.value=a.textarea_obj.value});e.subscribe("hiding",function(){c(document.body).removeClass("fullscreen-active");scrollTo(0,a.orig_y);c("#wpadminbar").show()});e.subscribe("hidden",function(){a.visible=false;c("#wp_mce_fullscreen").removeAttr("style");if(a.has_tinymce&&a.is_mce_on){tinyMCE.execCommand("wpFullScreenClose")}a.textarea_obj.value="";b.oldheight=0});e.subscribe("switchMode",function(h,g){var f;if(!a.has_tinymce||!a.is_mce_on){return}f=tinyMCE.get("wp_mce_fullscreen");if(h==="html"&&g==="tinymce"){a.textarea_obj.value=switchEditors.wpautop(a.textarea_obj.value);if("undefined"==typeof(f)){tinyMCE.execCommand("wpFullScreenInit")}else{f.show()}}else{if(h==="tinymce"&&g==="html"){if(f){f.hide()}}}});e.subscribe("switchedMode",function(g,f){b.refresh_buttons(true);if(f==="html"){setTimeout(b.resize_textarea,200)}});b.b=function(){if(a.has_tinymce&&"tinymce"===a.mode){tinyMCE.execCommand("Bold")}};b.i=function(){if(a.has_tinymce&&"tinymce"===a.mode){tinyMCE.execCommand("Italic")}};b.ul=function(){if(a.has_tinymce&&"tinymce"===a.mode){tinyMCE.execCommand("InsertUnorderedList")}};b.ol=function(){if(a.has_tinymce&&"tinymce"===a.mode){tinyMCE.execCommand("InsertOrderedList")}};b.link=function(){if(a.has_tinymce&&"tinymce"===a.mode){tinyMCE.execCommand("WP_Link")}else{wpLink.open()}};b.unlink=function(){if(a.has_tinymce&&"tinymce"===a.mode){tinyMCE.execCommand("unlink")}};b.atd=function(){if(a.has_tinymce&&"tinymce"===a.mode){tinyMCE.execCommand("mceWritingImprovementTool")}};b.help=function(){if(a.has_tinymce&&"tinymce"===a.mode){tinyMCE.execCommand("WP_Help")}};b.blockquote=function(){if(a.has_tinymce&&"tinymce"===a.mode){tinyMCE.execCommand("mceBlockQuote")}};b.refresh_buttons=function(f){f=f||false;if(a.mode==="html"){c("#wp-fullscreen-mode-bar").removeClass("wp-tmce-mode").addClass("wp-html-mode");if(f){c("#wp-fullscreen-button-bar").fadeOut(150,function(){c(this).addClass("wp-html-mode").fadeIn(150)})}else{c("#wp-fullscreen-button-bar").addClass("wp-html-mode")}}else{if(a.mode==="tinymce"){c("#wp-fullscreen-mode-bar").removeClass("wp-html-mode").addClass("wp-tmce-mode");if(f){c("#wp-fullscreen-button-bar").fadeOut(150,function(){c(this).removeClass("wp-html-mode").fadeIn(150)})}else{c("#wp-fullscreen-button-bar").removeClass("wp-html-mode")}}}};b.ui={init:function(){var f=c("#fullscreen-topbar"),h=c("#wp_mce_fullscreen"),g=0;a.toolbars=f.add(c("#wp-fullscreen-status"));a.element=c("#fullscreen-fader");a.textarea_obj=h[0];a.has_tinymce=typeof(tinyMCE)!="undefined";if(!a.has_tinymce){c("#wp-fullscreen-mode-bar").hide()}if(wptitlehint){wptitlehint("wp-fullscreen-title")}c(document).keyup(function(k){var l=k.keyCode||k.charCode,i,j;if(!fullscreen.settings.visible){return true}if(navigator.platform&&navigator.platform.indexOf("Mac")!=-1){i=k.ctrlKey}else{i=k.altKey}if(27==l){j={event:k,what:"dfw",cb:fullscreen.off,condition:function(){if(c("#TB_window").is(":visible")||c(".wp-dialog").is(":visible")){return false}return true}};if(!jQuery(document).triggerHandler("wp_CloseOnEscape",[j])){fullscreen.off()}}if(i&&(61==l||107==l||187==l)){b.dfw_width(25)}if(i&&(45==l||109==l||189==l)){b.dfw_width(-25)}if(i&&48==l){b.dfw_width(0)}return false});if(typeof(wpWordCount)!="undefined"){h.keyup(function(j){var i=j.keyCode||j.charCode;if(i==g){return true}if(13==i||8==g||46==g){c(document).triggerHandler("wpcountwords",[h.val()])}g=i;return true})}f.mouseenter(function(i){a.toolbars.addClass("fullscreen-make-sticky");c(document).unbind(".fullscreen");clearTimeout(a.timer);a.timer=0}).mouseleave(function(i){a.toolbars.removeClass("fullscreen-make-sticky");if(a.visible){c(document).bind("mousemove.fullscreen",function(j){d("showToolbar","hideToolbar",2000,j)})}})},fade:function(g,f,h){if(!a.element){b.ui.init()}if(g&&!e.publish(g)){return}b.fade.In(a.element,600,function(){if(f){e.publish(f)}b.fade.Out(a.element,600,function(){if(h){e.publish(h)}})})}};b.fade={transitionend:"transitionend webkitTransitionEnd oTransitionEnd",sensitivity:100,In:function(g,h,i,f){i=i||c.noop;h=h||400;f=f||false;if(b.fade.transitions){if(g.is(":visible")){g.addClass("fade-trigger");return g}g.show();g.first().one(this.transitionend,function(){i()});setTimeout(function(){g.addClass("fade-trigger")},this.sensitivity)}else{if(f){g.stop()}g.css("opacity",1);g.first().fadeIn(h,i);if(g.length>1){g.not(":first").fadeIn(h)}}return g},Out:function(g,h,i,f){i=i||c.noop;h=h||400;f=f||false;if(!g.is(":visible")){return g}if(b.fade.transitions){g.first().one(b.fade.transitionend,function(){if(g.hasClass("fade-trigger")){return}g.hide();i()});setTimeout(function(){g.removeClass("fade-trigger")},this.sensitivity)}else{if(f){g.stop()}g.first().fadeOut(h,i);if(g.length>1){g.not(":first").fadeOut(h)}}return g},transitions:(function(){var f=document.documentElement.style;return(typeof(f.WebkitTransition)=="string"||typeof(f.MozTransition)=="string"||typeof(f.OTransition)=="string"||typeof(f.transition)=="string")})()};b.bind_resize=function(){c(a.textarea_obj).bind("keypress.grow click.grow paste.grow",function(){setTimeout(b.resize_textarea,200)})};b.oldheight=0;b.resize_textarea=function(){var f=a.textarea_obj,g;g=f.scrollHeight>300?f.scrollHeight:300;if(g!=b.oldheight){f.style.height=g+"px";b.oldheight=g}}})(jQuery); \ No newline at end of file diff --git a/spec/samples/common/models/wp_version/findable/advanced_fingerprinting/wp_versions.xml b/spec/samples/common/models/wp_version/findable/advanced_fingerprinting/wp_versions.xml deleted file mode 100644 index 15cf7bdb..00000000 --- a/spec/samples/common/models/wp_version/findable/advanced_fingerprinting/wp_versions.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - 3.2.1 - - - - 3.2 - - - diff --git a/spec/samples/common/models/wp_version/findable/atom_generator/3.3.2.html b/spec/samples/common/models/wp_version/findable/atom_generator/3.3.2.html deleted file mode 100644 index 59895743..00000000 --- a/spec/samples/common/models/wp_version/findable/atom_generator/3.3.2.html +++ /dev/null @@ -1,33 +0,0 @@ - - Matt Mullenweg - Unlucky in Cards - - 2012-10-26T18:25:32Z - - - http://ma.tt/feed/atom/ - - - WordPress - - - - Matt - http://ma.tt/ - - <![CDATA[New Jetpack]]> - - http://ma.tt/?p=41967 - 2012-10-26T18:25:32Z - 2012-10-26T18:25:32Z - - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form.

-]]>
- - - 2 -
- -
diff --git a/spec/samples/common/models/wp_version/findable/atom_generator/3.4-beta4.html b/spec/samples/common/models/wp_version/findable/atom_generator/3.4-beta4.html deleted file mode 100644 index 34885b67..00000000 --- a/spec/samples/common/models/wp_version/findable/atom_generator/3.4-beta4.html +++ /dev/null @@ -1,33 +0,0 @@ - - Matt Mullenweg - Unlucky in Cards - - 2012-10-26T18:25:32Z - - - http://ma.tt/feed/atom/ - - - WordPress - - - - Matt - http://ma.tt/ - - <![CDATA[New Jetpack]]> - - http://ma.tt/?p=41967 - 2012-10-26T18:25:32Z - 2012-10-26T18:25:32Z - - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form.

-]]>
- - - 2 -
- -
diff --git a/spec/samples/common/models/wp_version/findable/atom_generator/invalid_version.html b/spec/samples/common/models/wp_version/findable/atom_generator/invalid_version.html deleted file mode 100644 index eb38e2e7..00000000 --- a/spec/samples/common/models/wp_version/findable/atom_generator/invalid_version.html +++ /dev/null @@ -1,33 +0,0 @@ - - Matt Mullenweg - Unlucky in Cards - - 2012-10-26T18:25:32Z - - - http://ma.tt/feed/atom/ - - - WordPress - - - - Matt - http://ma.tt/ - - <![CDATA[New Jetpack]]> - - http://ma.tt/?p=41967 - 2012-10-26T18:25:32Z - 2012-10-26T18:25:32Z - - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form.

-]]>
- - - 2 -
- -
diff --git a/spec/samples/common/models/wp_version/findable/atom_generator/no_generator.html b/spec/samples/common/models/wp_version/findable/atom_generator/no_generator.html deleted file mode 100644 index ddbb741c..00000000 --- a/spec/samples/common/models/wp_version/findable/atom_generator/no_generator.html +++ /dev/null @@ -1,32 +0,0 @@ - - Matt Mullenweg - Unlucky in Cards - - 2012-10-26T18:25:32Z - - - http://ma.tt/feed/atom/ - - - - - - Matt - http://ma.tt/ - - <![CDATA[New Jetpack]]> - - http://ma.tt/?p=41967 - 2012-10-26T18:25:32Z - 2012-10-26T18:25:32Z - - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form.

-]]>
- - - 2 -
- -
diff --git a/spec/samples/common/models/wp_version/findable/atom_generator/no_version.html b/spec/samples/common/models/wp_version/findable/atom_generator/no_version.html deleted file mode 100644 index e0c1008d..00000000 --- a/spec/samples/common/models/wp_version/findable/atom_generator/no_version.html +++ /dev/null @@ -1,33 +0,0 @@ - - Matt Mullenweg - Unlucky in Cards - - 2012-10-26T18:25:32Z - - - http://ma.tt/feed/atom/ - - - WordPress - - - - Matt - http://ma.tt/ - - <![CDATA[New Jetpack]]> - - http://ma.tt/?p=41967 - 2012-10-26T18:25:32Z - 2012-10-26T18:25:32Z - - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form.

-]]>
- - - 2 -
- -
diff --git a/spec/samples/common/models/wp_version/findable/links_opml/3.4.2.xml b/spec/samples/common/models/wp_version/findable/links_opml/3.4.2.xml deleted file mode 100644 index c20a5550..00000000 --- a/spec/samples/common/models/wp_version/findable/links_opml/3.4.2.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - Title - Mon, 24 Sep 2012 15:58:41 GMT - - - - - \ No newline at end of file diff --git a/spec/samples/common/models/wp_version/findable/links_opml/no_generator.xml b/spec/samples/common/models/wp_version/findable/links_opml/no_generator.xml deleted file mode 100644 index 97c27ad6..00000000 --- a/spec/samples/common/models/wp_version/findable/links_opml/no_generator.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - Title - Mon, 24 Sep 2012 15:58:41 GMT - - - - \ No newline at end of file diff --git a/spec/samples/common/models/wp_version/findable/meta_generator/3.3.2.html b/spec/samples/common/models/wp_version/findable/meta_generator/3.3.2.html deleted file mode 100644 index a082c08f..00000000 --- a/spec/samples/common/models/wp_version/findable/meta_generator/3.3.2.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - -Wordpress 3.3.2 | Just another WordPress site - - - - - - - - - - - - - - - - diff --git a/spec/samples/common/models/wp_version/findable/meta_generator/3.4-beta4.html b/spec/samples/common/models/wp_version/findable/meta_generator/3.4-beta4.html deleted file mode 100644 index 6459ce8f..00000000 --- a/spec/samples/common/models/wp_version/findable/meta_generator/3.4-beta4.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - -Wordpress 3.4 beta 4 | Just another WordPress site - - - - - - - - - - - - - diff --git a/spec/samples/common/models/wp_version/findable/meta_generator/3.5.1_mobile.html b/spec/samples/common/models/wp_version/findable/meta_generator/3.5.1_mobile.html deleted file mode 100644 index a555dca7..00000000 --- a/spec/samples/common/models/wp_version/findable/meta_generator/3.5.1_mobile.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - -Test - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spec/samples/common/models/wp_version/findable/meta_generator/3.5_minified.html b/spec/samples/common/models/wp_version/findable/meta_generator/3.5_minified.html deleted file mode 100644 index e65efd3f..00000000 --- a/spec/samples/common/models/wp_version/findable/meta_generator/3.5_minified.html +++ /dev/null @@ -1 +0,0 @@ -
  1. Zum Inhalt springen...
  2. Zur Navigation springen...
  3. Zu den Instituten springen...
  4. \ No newline at end of file diff --git a/spec/samples/common/models/wp_version/findable/meta_generator/invalid_version.html b/spec/samples/common/models/wp_version/findable/meta_generator/invalid_version.html deleted file mode 100644 index 0ff860eb..00000000 --- a/spec/samples/common/models/wp_version/findable/meta_generator/invalid_version.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - -Wordpress 3.3.2 | Just another WordPress site - - - - - - - - - - - - - - - - diff --git a/spec/samples/common/models/wp_version/findable/meta_generator/no_generator.html b/spec/samples/common/models/wp_version/findable/meta_generator/no_generator.html deleted file mode 100644 index 3eca3786..00000000 --- a/spec/samples/common/models/wp_version/findable/meta_generator/no_generator.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - -Wordpress 3.3.2 | Just another WordPress site - - - - - - - - - - - - - -
    - - - -
    -
    -
    - - - - - - - - - - -
    -
    - - - -
    - - -
    - - - - \ No newline at end of file diff --git a/spec/samples/common/models/wp_version/findable/meta_generator/no_version.html b/spec/samples/common/models/wp_version/findable/meta_generator/no_version.html deleted file mode 100644 index 7fef49fd..00000000 --- a/spec/samples/common/models/wp_version/findable/meta_generator/no_version.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - -Wordpress 3.3.2 | Just another WordPress site - - - - - - - - - - - - - - - - diff --git a/spec/samples/common/models/wp_version/findable/rdf_generator/3.3.2.html b/spec/samples/common/models/wp_version/findable/rdf_generator/3.3.2.html deleted file mode 100644 index 8bb588ff..00000000 --- a/spec/samples/common/models/wp_version/findable/rdf_generator/3.3.2.html +++ /dev/null @@ -1,57 +0,0 @@ - - - Matt Mullenweg - http://ma.tt - Unlucky in Cards - 2012-10-26T18:25:32Z - hourly - 1 - 2000-01-01T12:00+00:00 - - - - - - - - - - - New Jetpack - http://ma.tt/2012/10/new-jetpack/ - 2012-10-26T18:25:32Z - Matt - - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form. - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form.

    -]]>
    -
    - - Pandora and Artist Payments - http://ma.tt/2012/10/pandora-and-artist-payments/ - 2012-10-09T22:55:07Z - Matt - - Pandora and Artist Payments, about how Pandora is paying out millions of dollars to artists but is only 6.5% of the US radio listening audience, the fees the rest pay are far, far lower. - Pandora and Artist Payments, about how Pandora is paying out millions of dollars to artists but is only 6.5% of the US radio listening audience, the fees the rest pay are far, far lower.

    -]]>
    -
    - - Bitcoin and decentralization - http://ma.tt/2012/10/bitcoin-and-decentralization/ - 2012-10-06T19:53:54Z - Matt - - The value of Bitcoin is in its decentralization. - The value of Bitcoin is in its decentralization.

    -]]>
    -
    - -
    \ No newline at end of file diff --git a/spec/samples/common/models/wp_version/findable/rdf_generator/3.4-beta4.html b/spec/samples/common/models/wp_version/findable/rdf_generator/3.4-beta4.html deleted file mode 100644 index c4fb1787..00000000 --- a/spec/samples/common/models/wp_version/findable/rdf_generator/3.4-beta4.html +++ /dev/null @@ -1,57 +0,0 @@ - - - Matt Mullenweg - http://ma.tt - Unlucky in Cards - 2012-10-26T18:25:32Z - hourly - 1 - 2000-01-01T12:00+00:00 - - - - - - - - - - - New Jetpack - http://ma.tt/2012/10/new-jetpack/ - 2012-10-26T18:25:32Z - Matt - - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form. - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form.

    -]]>
    -
    - - Pandora and Artist Payments - http://ma.tt/2012/10/pandora-and-artist-payments/ - 2012-10-09T22:55:07Z - Matt - - Pandora and Artist Payments, about how Pandora is paying out millions of dollars to artists but is only 6.5% of the US radio listening audience, the fees the rest pay are far, far lower. - Pandora and Artist Payments, about how Pandora is paying out millions of dollars to artists but is only 6.5% of the US radio listening audience, the fees the rest pay are far, far lower.

    -]]>
    -
    - - Bitcoin and decentralization - http://ma.tt/2012/10/bitcoin-and-decentralization/ - 2012-10-06T19:53:54Z - Matt - - The value of Bitcoin is in its decentralization. - The value of Bitcoin is in its decentralization.

    -]]>
    -
    - -
    \ No newline at end of file diff --git a/spec/samples/common/models/wp_version/findable/rdf_generator/invalid_version.html b/spec/samples/common/models/wp_version/findable/rdf_generator/invalid_version.html deleted file mode 100644 index 2c3de494..00000000 --- a/spec/samples/common/models/wp_version/findable/rdf_generator/invalid_version.html +++ /dev/null @@ -1,57 +0,0 @@ - - - Matt Mullenweg - http://ma.tt - Unlucky in Cards - 2012-10-26T18:25:32Z - hourly - 1 - 2000-01-01T12:00+00:00 - - - - - - - - - - - New Jetpack - http://ma.tt/2012/10/new-jetpack/ - 2012-10-26T18:25:32Z - Matt - - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form. - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form.

    -]]>
    -
    - - Pandora and Artist Payments - http://ma.tt/2012/10/pandora-and-artist-payments/ - 2012-10-09T22:55:07Z - Matt - - Pandora and Artist Payments, about how Pandora is paying out millions of dollars to artists but is only 6.5% of the US radio listening audience, the fees the rest pay are far, far lower. - Pandora and Artist Payments, about how Pandora is paying out millions of dollars to artists but is only 6.5% of the US radio listening audience, the fees the rest pay are far, far lower.

    -]]>
    -
    - - Bitcoin and decentralization - http://ma.tt/2012/10/bitcoin-and-decentralization/ - 2012-10-06T19:53:54Z - Matt - - The value of Bitcoin is in its decentralization. - The value of Bitcoin is in its decentralization.

    -]]>
    -
    - -
    \ No newline at end of file diff --git a/spec/samples/common/models/wp_version/findable/rdf_generator/no_generator.html b/spec/samples/common/models/wp_version/findable/rdf_generator/no_generator.html deleted file mode 100644 index 6bb1523c..00000000 --- a/spec/samples/common/models/wp_version/findable/rdf_generator/no_generator.html +++ /dev/null @@ -1,56 +0,0 @@ - - - Matt Mullenweg - http://ma.tt - Unlucky in Cards - 2012-10-26T18:25:32Z - hourly - 1 - 2000-01-01T12:00+00:00 - - - - - - - - - - New Jetpack - http://ma.tt/2012/10/new-jetpack/ - 2012-10-26T18:25:32Z - Matt - - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form. - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form.

    -]]>
    -
    - - Pandora and Artist Payments - http://ma.tt/2012/10/pandora-and-artist-payments/ - 2012-10-09T22:55:07Z - Matt - - Pandora and Artist Payments, about how Pandora is paying out millions of dollars to artists but is only 6.5% of the US radio listening audience, the fees the rest pay are far, far lower. - Pandora and Artist Payments, about how Pandora is paying out millions of dollars to artists but is only 6.5% of the US radio listening audience, the fees the rest pay are far, far lower.

    -]]>
    -
    - - Bitcoin and decentralization - http://ma.tt/2012/10/bitcoin-and-decentralization/ - 2012-10-06T19:53:54Z - Matt - - The value of Bitcoin is in its decentralization. - The value of Bitcoin is in its decentralization.

    -]]>
    -
    - -
    \ No newline at end of file diff --git a/spec/samples/common/models/wp_version/findable/rdf_generator/no_version.html b/spec/samples/common/models/wp_version/findable/rdf_generator/no_version.html deleted file mode 100644 index c7c0610b..00000000 --- a/spec/samples/common/models/wp_version/findable/rdf_generator/no_version.html +++ /dev/null @@ -1,57 +0,0 @@ - - - Matt Mullenweg - http://ma.tt - Unlucky in Cards - 2012-10-26T18:25:32Z - hourly - 1 - 2000-01-01T12:00+00:00 - - - - - - - - - - - New Jetpack - http://ma.tt/2012/10/new-jetpack/ - 2012-10-26T18:25:32Z - Matt - - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form. - I’m really excited abou the new Jetpack, it includes toolbar notifications, mobile push for iOS, a new REST API, and fixes to the contact form.

    -]]>
    -
    - - Pandora and Artist Payments - http://ma.tt/2012/10/pandora-and-artist-payments/ - 2012-10-09T22:55:07Z - Matt - - Pandora and Artist Payments, about how Pandora is paying out millions of dollars to artists but is only 6.5% of the US radio listening audience, the fees the rest pay are far, far lower. - Pandora and Artist Payments, about how Pandora is paying out millions of dollars to artists but is only 6.5% of the US radio listening audience, the fees the rest pay are far, far lower.

    -]]>
    -
    - - Bitcoin and decentralization - http://ma.tt/2012/10/bitcoin-and-decentralization/ - 2012-10-06T19:53:54Z - Matt - - The value of Bitcoin is in its decentralization. - The value of Bitcoin is in its decentralization.

    -]]>
    -
    - -
    \ No newline at end of file diff --git a/spec/samples/common/models/wp_version/findable/readme/3.3.2.html b/spec/samples/common/models/wp_version/findable/readme/3.3.2.html deleted file mode 100644 index 8980b379..00000000 --- a/spec/samples/common/models/wp_version/findable/readme/3.3.2.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - WordPress › ReadMe - - - -

    - WordPress -
    Version 3.3.2 -

    -

    Semantic Personal Publishing Platform

    - -

    First Things First

    -

    Welcome. WordPress is a very special project to me. Every developer and contributor adds something unique to the mix, and together we create something beautiful that I'm proud to be a part of. Thousands of hours have gone into WordPress, and we're dedicated to making it better every day. Thank you for making it part of your world.

    -

    — Matt Mullenweg

    - -

    Installation: Famous 5-minute install

    -
      -
    1. Unzip the package in an empty directory and upload everything.
    2. -
    3. Open wp-admin/install.php in your browser. It will take you through the process to set up a wp-config.php file with your database connection details. -
        -
      1. If for some reason this doesn't work, don't worry. It doesn't work on all web hosts. Open up wp-config-sample.php with a text editor like WordPad or similar and fill in your database connection details.
      2. -
      3. Save the file as wp-config.php and upload it.
      4. -
      5. Open wp-admin/install.php in your browser.
      6. -
      -
    4. -
    5. Once the configuration file is set up, the installer will set up the tables needed for your blog. If there is an error, double check your wp-config.php file, and try again. If it fails again, please go to the support forums with as much data as you can gather.
    6. -
    7. If you did not enter a password, note the password given to you. If you did not provide a username, it will be admin.
    8. -
    9. The installer should then send you to the login page. Sign in with the username and password you chose during the installation. If a password was generated for you, you can then click on 'Profile' to change the password.
    10. -
    - -

    Updating

    -

    Using the Automatic Updater

    -

    If you are updating from version 2.7 or higher, you can use the automatic updater:

    -
      -
    1. Open the wp-admin/update-core.php in your browser and follow the instructions.
    2. -
    3. You wanted more, perhaps? That's it!
    4. -
    - -

    Updating Manually

    -
      -
    1. Before you update anything, make sure you have backup copies of any files you may have modified such as index.php.
    2. -
    3. Delete your old WordPress files, saving ones you've modified.
    4. -
    5. Upload the new files.
    6. -
    7. Point your browser to /wp-admin/upgrade.php.
    8. -
    - -

    Theme Template Changes

    -

    If you have customized your theme templates, you may have to make some changes across major versions.

    - -

    Migrating from other systems

    -

    WordPress can import from a number of systems. First you need to get WordPress installed and working as described above, before using our import tools.

    - -

    System Requirements

    -
      -
    • PHP version 5.2.4 or higher.
    • -
    • MySQL version 5.0 or higher.
    • -
    - -

    System Recommendations

    - - -

    Online Resources

    -

    If you have any questions that aren't addressed in this document, please take advantage of WordPress' numerous online resources:

    -
    -
    The WordPress Codex
    -
    The Codex is the encyclopedia of all things WordPress. It is the most comprehensive source of information for WordPress available.
    -
    The WordPress Blog
    -
    This is where you'll find the latest updates and news related to WordPress. Recent WordPress news appears in your administrative dashboard by default.
    -
    WordPress Planet
    -
    The WordPress Planet is a news aggregator that brings together posts from WordPress blogs around the web.
    -
    WordPress Support Forums
    -
    If you've looked everywhere and still can't find an answer, the support forums are very active and have a large community ready to help. To help them help you be sure to use a descriptive thread title and describe your question in as much detail as possible.
    -
    WordPress IRC Channel
    -
    There is an online chat channel that is used for discussion among people who use WordPress and occasionally support topics. The above wiki page should point you in the right direction. (irc.freenode.net #wordpress)
    -
    - -

    XML-RPC and Atom Interface

    -

    You can post to your WordPress blog with tools like Windows Live Writer, Ecto, w.bloggar, Radio Userland (which means you can use Radio's email-to-blog feature), NewzCrawler, and other tools that support the blogging APIs! :) You can read more about XML-RPC support on the Codex.

    - -

    Post via Email

    -

    You can post from an email client! To set this up go to your "Writing" options screen and fill in the connection details for your secret POP3 account. Then you need to set up wp-mail.php to execute periodically to check the mailbox for new posts. You can do it with cron-jobs, or if your host doesn't support it you can look into the various website-monitoring services, and make them check your wp-mail.php URL.

    -

    Posting is easy: Any email sent to the address you specify will be posted, with the subject as the title. It is best to keep the address discrete. The script will delete emails that are successfully posted.

    - -

    User Roles

    -

    We introduced a very flexible roles system in version 2.0. You can read more about Roles and Capabilities on the Codex.

    - -

    Final Notes

    -
      -
    • If you have any suggestions, ideas, or comments, or if you (gasp!) found a bug, join us in the Support Forums.
    • -
    • WordPress has a robust plugin API that makes extending the code easy. If you are a developer interested in utilizing this, see the plugin documentation in the Codex. You shouldn't modify any of the core code.
    • -
    - -

    Share the Love

    -

    WordPress has no multi-million dollar marketing campaign or celebrity sponsors, but we do have something even better—you. If you enjoy WordPress please consider telling a friend, setting it up for someone less knowledgable than yourself, or writing the author of a media article that overlooks us.

    - -

    WordPress is the official continuation of b2/cafélog, which came from Michel V. The work has been continued by the WordPress developers. If you would like to support WordPress, please consider donating.

    - -

    License

    -

    WordPress is free software, and is released under the terms of the GPL version 2 or (at your option) any later version. See license.txt.

    - - - - diff --git a/spec/samples/common/models/wp_version/findable/readme/4.7.2.html b/spec/samples/common/models/wp_version/findable/readme/4.7.2.html deleted file mode 100644 index f94226c3..00000000 --- a/spec/samples/common/models/wp_version/findable/readme/4.7.2.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - WordPress › ReadMe - - - -

    - WordPress -
    Version 4.7 -

    -

    Semantic Personal Publishing Platform

    - -

    First Things First

    -

    Welcome. WordPress is a very special project to me. Every developer and contributor adds something unique to the mix, and together we create something beautiful that I’m proud to be a part of. Thousands of hours have gone into WordPress, and we’re dedicated to making it better every day. Thank you for making it part of your world.

    -

    — Matt Mullenweg

    - -

    Installation: Famous 5-minute install

    -
      -
    1. Unzip the package in an empty directory and upload everything.
    2. -
    3. Open wp-admin/install.php in your browser. It will take you through the process to set up a wp-config.php file with your database connection details. -
        -
      1. If for some reason this doesn’t work, don’t worry. It doesn’t work on all web hosts. Open up wp-config-sample.php with a text editor like WordPad or similar and fill in your database connection details.
      2. -
      3. Save the file as wp-config.php and upload it.
      4. -
      5. Open wp-admin/install.php in your browser.
      6. -
      -
    4. -
    5. Once the configuration file is set up, the installer will set up the tables needed for your blog. If there is an error, double check your wp-config.php file, and try again. If it fails again, please go to the support forums with as much data as you can gather.
    6. -
    7. If you did not enter a password, note the password given to you. If you did not provide a username, it will be admin.
    8. -
    9. The installer should then send you to the login page. Sign in with the username and password you chose during the installation. If a password was generated for you, you can then click on “Profile” to change the password.
    10. -
    - -

    Updating

    -

    Using the Automatic Updater

    -

    If you are updating from version 2.7 or higher, you can use the automatic updater:

    -
      -
    1. Open wp-admin/update-core.php in your browser and follow the instructions.
    2. -
    3. You wanted more, perhaps? That’s it!
    4. -
    - -

    Updating Manually

    -
      -
    1. Before you update anything, make sure you have backup copies of any files you may have modified such as index.php.
    2. -
    3. Delete your old WordPress files, saving ones you’ve modified.
    4. -
    5. Upload the new files.
    6. -
    7. Point your browser to /wp-admin/upgrade.php.
    8. -
    - -

    Migrating from other systems

    -

    WordPress can import from a number of systems. First you need to get WordPress installed and working as described above, before using our import tools.

    - -

    System Requirements

    -
      -
    • PHP version 5.2.4 or higher.
    • -
    • MySQL version 5.0 or higher.
    • -
    - -

    Recommendations

    - - -

    Online Resources

    -

    If you have any questions that aren’t addressed in this document, please take advantage of WordPress’ numerous online resources:

    -
    -
    The WordPress Codex
    -
    The Codex is the encyclopedia of all things WordPress. It is the most comprehensive source of information for WordPress available.
    -
    The WordPress Blog
    -
    This is where you’ll find the latest updates and news related to WordPress. Recent WordPress news appears in your administrative dashboard by default.
    -
    WordPress Planet
    -
    The WordPress Planet is a news aggregator that brings together posts from WordPress blogs around the web.
    -
    WordPress Support Forums
    -
    If you’ve looked everywhere and still can’t find an answer, the support forums are very active and have a large community ready to help. To help them help you be sure to use a descriptive thread title and describe your question in as much detail as possible.
    -
    WordPress IRC Channel
    -
    There is an online chat channel that is used for discussion among people who use WordPress and occasionally support topics. The above wiki page should point you in the right direction. (irc.freenode.net #wordpress)
    -
    - -

    Final Notes

    -
      -
    • If you have any suggestions, ideas, or comments, or if you (gasp!) found a bug, join us in the Support Forums.
    • -
    • WordPress has a robust plugin API that makes extending the code easy. If you are a developer interested in utilizing this, see the Plugin Developer Handbook. You shouldn’t modify any of the core code.
    • -
    - -

    Share the Love

    -

    WordPress has no multi-million dollar marketing campaign or celebrity sponsors, but we do have something even better—you. If you enjoy WordPress please consider telling a friend, setting it up for someone less knowledgable than yourself, or writing the author of a media article that overlooks us.

    - -

    WordPress is the official continuation of b2/cafélog, which came from Michel V. The work has been continued by the WordPress developers. If you would like to support WordPress, please consider donating.

    - -

    License

    -

    WordPress is free software, and is released under the terms of the GPL version 2 or (at your option) any later version. See license.txt.

    - - - diff --git a/spec/samples/common/models/wp_version/findable/readme/empty_version.html b/spec/samples/common/models/wp_version/findable/readme/empty_version.html deleted file mode 100644 index 11d22c4c..00000000 --- a/spec/samples/common/models/wp_version/findable/readme/empty_version.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - WordPress › ReadMe - - - -

    - WordPress -
    Version -

    -

    Semantic Personal Publishing Platform

    - -

    First Things First

    -

    Welcome. WordPress is a very special project to me. Every developer and contributor adds something unique to the mix, and together we create something beautiful that I'm proud to be a part of. Thousands of hours have gone into WordPress, and we're dedicated to making it better every day. Thank you for making it part of your world.

    -

    — Matt Mullenweg

    - -

    Installation: Famous 5-minute install

    -
      -
    1. Unzip the package in an empty directory and upload everything.
    2. -
    3. Open wp-admin/install.php in your browser. It will take you through the process to set up a wp-config.php file with your database connection details. -
        -
      1. If for some reason this doesn't work, don't worry. It doesn't work on all web hosts. Open up wp-config-sample.php with a text editor like WordPad or similar and fill in your database connection details.
      2. -
      3. Save the file as wp-config.php and upload it.
      4. -
      5. Open wp-admin/install.php in your browser.
      6. -
      -
    4. -
    5. Once the configuration file is set up, the installer will set up the tables needed for your blog. If there is an error, double check your wp-config.php file, and try again. If it fails again, please go to the support forums with as much data as you can gather.
    6. -
    7. If you did not enter a password, note the password given to you. If you did not provide a username, it will be admin.
    8. -
    9. The installer should then send you to the login page. Sign in with the username and password you chose during the installation. If a password was generated for you, you can then click on 'Profile' to change the password.
    10. -
    - -

    Updating

    -

    Using the Automatic Updater

    -

    If you are updating from version 2.7 or higher, you can use the automatic updater:

    -
      -
    1. Open the wp-admin/update-core.php in your browser and follow the instructions.
    2. -
    3. You wanted more, perhaps? That's it!
    4. -
    - -

    Updating Manually

    -
      -
    1. Before you update anything, make sure you have backup copies of any files you may have modified such as index.php.
    2. -
    3. Delete your old WordPress files, saving ones you've modified.
    4. -
    5. Upload the new files.
    6. -
    7. Point your browser to /wp-admin/upgrade.php.
    8. -
    - -

    Theme Template Changes

    -

    If you have customized your theme templates, you may have to make some changes across major versions.

    - -

    Migrating from other systems

    -

    WordPress can import from a number of systems. First you need to get WordPress installed and working as described above, before using our import tools.

    - -

    System Requirements

    -
      -
    • PHP version 5.2.4 or higher.
    • -
    • MySQL version 5.0 or higher.
    • -
    - -

    System Recommendations

    - - -

    Online Resources

    -

    If you have any questions that aren't addressed in this document, please take advantage of WordPress' numerous online resources:

    -
    -
    The WordPress Codex
    -
    The Codex is the encyclopedia of all things WordPress. It is the most comprehensive source of information for WordPress available.
    -
    The WordPress Blog
    -
    This is where you'll find the latest updates and news related to WordPress. Recent WordPress news appears in your administrative dashboard by default.
    -
    WordPress Planet
    -
    The WordPress Planet is a news aggregator that brings together posts from WordPress blogs around the web.
    -
    WordPress Support Forums
    -
    If you've looked everywhere and still can't find an answer, the support forums are very active and have a large community ready to help. To help them help you be sure to use a descriptive thread title and describe your question in as much detail as possible.
    -
    WordPress IRC Channel
    -
    There is an online chat channel that is used for discussion among people who use WordPress and occasionally support topics. The above wiki page should point you in the right direction. (irc.freenode.net #wordpress)
    -
    - -

    XML-RPC and Atom Interface

    -

    You can post to your WordPress blog with tools like Windows Live Writer, Ecto, w.bloggar, Radio Userland (which means you can use Radio's email-to-blog feature), NewzCrawler, and other tools that support the blogging APIs! :) You can read more about XML-RPC support on the Codex.

    - -

    Post via Email

    -

    You can post from an email client! To set this up go to your "Writing" options screen and fill in the connection details for your secret POP3 account. Then you need to set up wp-mail.php to execute periodically to check the mailbox for new posts. You can do it with cron-jobs, or if your host doesn't support it you can look into the various website-monitoring services, and make them check your wp-mail.php URL.

    -

    Posting is easy: Any email sent to the address you specify will be posted, with the subject as the title. It is best to keep the address discrete. The script will delete emails that are successfully posted.

    - -

    User Roles

    -

    We introduced a very flexible roles system in version 2.0. You can read more about Roles and Capabilities on the Codex.

    - -

    Final Notes

    -
      -
    • If you have any suggestions, ideas, or comments, or if you (gasp!) found a bug, join us in the Support Forums.
    • -
    • WordPress has a robust plugin API that makes extending the code easy. If you are a developer interested in utilizing this, see the plugin documentation in the Codex. You shouldn't modify any of the core code.
    • -
    - -

    Share the Love

    -

    WordPress has no multi-million dollar marketing campaign or celebrity sponsors, but we do have something even better—you. If you enjoy WordPress please consider telling a friend, setting it up for someone less knowledgable than yourself, or writing the author of a media article that overlooks us.

    - -

    WordPress is the official continuation of b2/cafélog, which came from Michel V. The work has been continued by the WordPress developers. If you would like to support WordPress, please consider donating.

    - -

    License

    -

    WordPress is free software, and is released under the terms of the GPL version 2 or (at your option) any later version. See license.txt.

    - - - - diff --git a/spec/samples/common/models/wp_version/findable/readme/invalid_version.html b/spec/samples/common/models/wp_version/findable/readme/invalid_version.html deleted file mode 100644 index 16fb9adb..00000000 --- a/spec/samples/common/models/wp_version/findable/readme/invalid_version.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - WordPress › ReadMe - - - -

    - WordPress -
    Version 5506 -

    -

    Semantic Personal Publishing Platform

    - -

    First Things First

    -

    Welcome. WordPress is a very special project to me. Every developer and contributor adds something unique to the mix, and together we create something beautiful that I'm proud to be a part of. Thousands of hours have gone into WordPress, and we're dedicated to making it better every day. Thank you for making it part of your world.

    -

    — Matt Mullenweg

    - -

    Installation: Famous 5-minute install

    -
      -
    1. Unzip the package in an empty directory and upload everything.
    2. -
    3. Open wp-admin/install.php in your browser. It will take you through the process to set up a wp-config.php file with your database connection details. -
        -
      1. If for some reason this doesn't work, don't worry. It doesn't work on all web hosts. Open up wp-config-sample.php with a text editor like WordPad or similar and fill in your database connection details.
      2. -
      3. Save the file as wp-config.php and upload it.
      4. -
      5. Open wp-admin/install.php in your browser.
      6. -
      -
    4. -
    5. Once the configuration file is set up, the installer will set up the tables needed for your blog. If there is an error, double check your wp-config.php file, and try again. If it fails again, please go to the support forums with as much data as you can gather.
    6. -
    7. If you did not enter a password, note the password given to you. If you did not provide a username, it will be admin.
    8. -
    9. The installer should then send you to the login page. Sign in with the username and password you chose during the installation. If a password was generated for you, you can then click on 'Profile' to change the password.
    10. -
    - -

    Updating

    -

    Using the Automatic Updater

    -

    If you are updating from version 2.7 or higher, you can use the automatic updater:

    -
      -
    1. Open the wp-admin/update-core.php in your browser and follow the instructions.
    2. -
    3. You wanted more, perhaps? That's it!
    4. -
    - -

    Updating Manually

    -
      -
    1. Before you update anything, make sure you have backup copies of any files you may have modified such as index.php.
    2. -
    3. Delete your old WordPress files, saving ones you've modified.
    4. -
    5. Upload the new files.
    6. -
    7. Point your browser to /wp-admin/upgrade.php.
    8. -
    - -

    Theme Template Changes

    -

    If you have customized your theme templates, you may have to make some changes across major versions.

    - -

    Migrating from other systems

    -

    WordPress can import from a number of systems. First you need to get WordPress installed and working as described above, before using our import tools.

    - -

    System Requirements

    -
      -
    • PHP version 5.2.4 or higher.
    • -
    • MySQL version 5.0 or higher.
    • -
    - -

    System Recommendations

    - - -

    Online Resources

    -

    If you have any questions that aren't addressed in this document, please take advantage of WordPress' numerous online resources:

    -
    -
    The WordPress Codex
    -
    The Codex is the encyclopedia of all things WordPress. It is the most comprehensive source of information for WordPress available.
    -
    The WordPress Blog
    -
    This is where you'll find the latest updates and news related to WordPress. Recent WordPress news appears in your administrative dashboard by default.
    -
    WordPress Planet
    -
    The WordPress Planet is a news aggregator that brings together posts from WordPress blogs around the web.
    -
    WordPress Support Forums
    -
    If you've looked everywhere and still can't find an answer, the support forums are very active and have a large community ready to help. To help them help you be sure to use a descriptive thread title and describe your question in as much detail as possible.
    -
    WordPress IRC Channel
    -
    There is an online chat channel that is used for discussion among people who use WordPress and occasionally support topics. The above wiki page should point you in the right direction. (irc.freenode.net #wordpress)
    -
    - -

    XML-RPC and Atom Interface

    -

    You can post to your WordPress blog with tools like Windows Live Writer, Ecto, w.bloggar, Radio Userland (which means you can use Radio's email-to-blog feature), NewzCrawler, and other tools that support the blogging APIs! :) You can read more about XML-RPC support on the Codex.

    - -

    Post via Email

    -

    You can post from an email client! To set this up go to your "Writing" options screen and fill in the connection details for your secret POP3 account. Then you need to set up wp-mail.php to execute periodically to check the mailbox for new posts. You can do it with cron-jobs, or if your host doesn't support it you can look into the various website-monitoring services, and make them check your wp-mail.php URL.

    -

    Posting is easy: Any email sent to the address you specify will be posted, with the subject as the title. It is best to keep the address discrete. The script will delete emails that are successfully posted.

    - -

    User Roles

    -

    We introduced a very flexible roles system in version 2.0. You can read more about Roles and Capabilities on the Codex.

    - -

    Final Notes

    -
      -
    • If you have any suggestions, ideas, or comments, or if you (gasp!) found a bug, join us in the Support Forums.
    • -
    • WordPress has a robust plugin API that makes extending the code easy. If you are a developer interested in utilizing this, see the plugin documentation in the Codex. You shouldn't modify any of the core code.
    • -
    - -

    Share the Love

    -

    WordPress has no multi-million dollar marketing campaign or celebrity sponsors, but we do have something even better—you. If you enjoy WordPress please consider telling a friend, setting it up for someone less knowledgable than yourself, or writing the author of a media article that overlooks us.

    - -

    WordPress is the official continuation of b2/cafélog, which came from Michel V. The work has been continued by the WordPress developers. If you would like to support WordPress, please consider donating.

    - -

    License

    -

    WordPress is free software, and is released under the terms of the GPL version 2 or (at your option) any later version. See license.txt.

    - - - - diff --git a/spec/samples/common/models/wp_version/findable/rss_generator/3.3.2.html b/spec/samples/common/models/wp_version/findable/rss_generator/3.3.2.html deleted file mode 100644 index e730a810..00000000 --- a/spec/samples/common/models/wp_version/findable/rss_generator/3.3.2.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - Wordpress 3.3.2 - - http://lamp/wordpress-3.3.2 - Just another WordPress site - Wed, 02 May 2012 13:05:44 +0000 - en - hourly - 1 - http://wordpress.org/?v=3.3.2 - - Hello world! - http://lamp/wordpress-3.3.2/?p=1 - http://lamp/wordpress-3.3.2/?p=1#comments - Wed, 02 May 2012 13:05:44 +0000 - admin - - - http://lamp/wordpress-3.3.2/?p=1 - - Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!

    -]]>
    - http://lamp/wordpress-3.3.2/?feed=rss2&p=1 - 2 -
    -
    -
    diff --git a/spec/samples/common/models/wp_version/findable/rss_generator/3.4-beta4.html b/spec/samples/common/models/wp_version/findable/rss_generator/3.4-beta4.html deleted file mode 100644 index 1b5c16f0..00000000 --- a/spec/samples/common/models/wp_version/findable/rss_generator/3.4-beta4.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - Wordpress 3.4 beta 4 - - http://lamp/wordpress-3.4-beta-4 - Just another WordPress site - Wed, 09 May 2012 16:29:08 +0000 - en-US - hourly - 1 - http://wordpress.org/?v=3.4-beta4 - - Hello world! - http://lamp/wordpress-3.4-beta-4/?p=1 - http://lamp/wordpress-3.4-beta-4/?p=1#comments - Wed, 09 May 2012 16:29:08 +0000 - admin - - - http://lamp/wordpress-3.4-beta-4/?p=1 - - Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!

    -]]>
    - http://lamp/wordpress-3.4-beta-4/?feed=rss2&p=1 - 1 -
    -
    -
    diff --git a/spec/samples/common/models/wp_version/findable/rss_generator/invalid_version.html b/spec/samples/common/models/wp_version/findable/rss_generator/invalid_version.html deleted file mode 100644 index 76a87ec6..00000000 --- a/spec/samples/common/models/wp_version/findable/rss_generator/invalid_version.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - Wordpress 3.3.2 - - http://lamp/wordpress-3.3.2 - Just another WordPress site - Wed, 02 May 2012 13:05:44 +0000 - en - hourly - 1 - http://wordpress.org/?v=5506 - - Hello world! - http://lamp/wordpress-3.3.2/?p=1 - http://lamp/wordpress-3.3.2/?p=1#comments - Wed, 02 May 2012 13:05:44 +0000 - admin - - - http://lamp/wordpress-3.3.2/?p=1 - - Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!

    -]]>
    - http://lamp/wordpress-3.3.2/?feed=rss2&p=1 - 2 -
    -
    -
    diff --git a/spec/samples/common/models/wp_version/findable/rss_generator/no_generator.html b/spec/samples/common/models/wp_version/findable/rss_generator/no_generator.html deleted file mode 100644 index 38a23409..00000000 --- a/spec/samples/common/models/wp_version/findable/rss_generator/no_generator.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - Wordpress 3.4 beta 4 - - http://lamp/wordpress-3.4-beta-4 - Just another WordPress site - Wed, 09 May 2012 16:29:08 +0000 - en-US - hourly - 1 - - Hello world! - http://lamp/wordpress-3.4-beta-4/?p=1 - http://lamp/wordpress-3.4-beta-4/?p=1#comments - Wed, 09 May 2012 16:29:08 +0000 - admin - - - http://lamp/wordpress-3.4-beta-4/?p=1 - - Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!

    -]]>
    - http://lamp/wordpress-3.4-beta-4/?feed=rss2&p=1 - 1 -
    -
    -
    diff --git a/spec/samples/common/models/wp_version/findable/rss_generator/no_version.html b/spec/samples/common/models/wp_version/findable/rss_generator/no_version.html deleted file mode 100644 index 7a0d3112..00000000 --- a/spec/samples/common/models/wp_version/findable/rss_generator/no_version.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - Wordpress 3.3.2 - - http://lamp/wordpress-3.3.2 - Just another WordPress site - Wed, 02 May 2012 13:05:44 +0000 - en - hourly - 1 - http://wordpress.org/?v= - - Hello world! - http://lamp/wordpress-3.3.2/?p=1 - http://lamp/wordpress-3.3.2/?p=1#comments - Wed, 02 May 2012 13:05:44 +0000 - admin - - - http://lamp/wordpress-3.3.2/?p=1 - - Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!

    -]]>
    - http://lamp/wordpress-3.3.2/?feed=rss2&p=1 - 2 -
    -
    -
    diff --git a/spec/samples/common/models/wp_version/findable/sitemap_generator/3.3.2.html b/spec/samples/common/models/wp_version/findable/sitemap_generator/3.3.2.html deleted file mode 100644 index 93cbf91a..00000000 --- a/spec/samples/common/models/wp_version/findable/sitemap_generator/3.3.2.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/spec/samples/common/models/wp_version/findable/sitemap_generator/3.4-beta4.html b/spec/samples/common/models/wp_version/findable/sitemap_generator/3.4-beta4.html deleted file mode 100644 index 9d7c35b0..00000000 --- a/spec/samples/common/models/wp_version/findable/sitemap_generator/3.4-beta4.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/spec/samples/common/models/wp_version/findable/sitemap_generator/invalid_version.html b/spec/samples/common/models/wp_version/findable/sitemap_generator/invalid_version.html deleted file mode 100644 index e6327ecc..00000000 --- a/spec/samples/common/models/wp_version/findable/sitemap_generator/invalid_version.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/spec/samples/common/models/wp_version/findable/sitemap_generator/no_generator.html b/spec/samples/common/models/wp_version/findable/sitemap_generator/no_generator.html deleted file mode 100644 index cf28468f..00000000 --- a/spec/samples/common/models/wp_version/findable/sitemap_generator/no_generator.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/spec/samples/common/models/wp_version/findable/sitemap_generator/no_version.html b/spec/samples/common/models/wp_version/findable/sitemap_generator/no_version.html deleted file mode 100644 index b4a404f3..00000000 --- a/spec/samples/common/models/wp_version/findable/sitemap_generator/no_version.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/spec/samples/common/models/wp_version/findable/stylesheet_numbers/invalid_url.html b/spec/samples/common/models/wp_version/findable/stylesheet_numbers/invalid_url.html deleted file mode 100644 index 04ccf538..00000000 --- a/spec/samples/common/models/wp_version/findable/stylesheet_numbers/invalid_url.html +++ /dev/null @@ -1,8 +0,0 @@ - - diff --git a/spec/samples/common/models/wp_version/vulnerable/versions_vulns.json b/spec/samples/common/models/wp_version/vulnerable/versions_vulns.json deleted file mode 100644 index 2d2407e4..00000000 --- a/spec/samples/common/models/wp_version/vulnerable/versions_vulns.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "3.5": { - "vulnerabilities":[ - { - "id":2989, - "title":"I should not appear in the results", - "references": { - "url": ["Ref 1", "Ref 2"], - "osvdb": ["osvdb"], - "cve": ["2011-001"], - "secunia": ["secunia"], - "metasploit": ["exploit/ex1"], - "exploitdb": ["exploitdb"] - }, - "type":"XSS", - "fixed_in":"", - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - } - ] - }, - "3.2": { - "vulnerabilities":[ - { - "id":2993, - "title":"Here I Am", - "references": { - "url": ["Ref 1", "Ref 2"], - "osvdb": ["osvdb"], - "cve": ["2011-001"], - "secunia": ["secunia"], - "metasploit": ["exploit/ex1"], - "exploitdb": ["exploitdb"] - }, - "type":"SQLI", - "fixed_in":"", - "created_at":"2014-07-28T12:10:07.000Z", - "updated_at":"2014-07-28T12:10:07.000Z" - } - ] - } -} diff --git a/spec/samples/conf/browser.conf.json b/spec/samples/conf/browser.conf.json deleted file mode 100644 index ab5d88de..00000000 --- a/spec/samples/conf/browser.conf.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0", - "cache_ttl": 600, - "request_timeout": 60, - "connect_timeout": 10, - "max_threads": 20 -} diff --git a/spec/samples/conf/browser.conf_proxy.json b/spec/samples/conf/browser.conf_proxy.json deleted file mode 100644 index f60413db..00000000 --- a/spec/samples/conf/browser.conf_proxy.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20100101 Firefox/11.0", - "proxy": "127.0.0.1:3038", - "cache_ttl": 300, - "request_timeout": 60, - "connect_timeout": 10 -} diff --git a/spec/samples/conf/browser.conf_proxy_auth.json b/spec/samples/conf/browser.conf_proxy_auth.json deleted file mode 100644 index 898e8f3d..00000000 --- a/spec/samples/conf/browser.conf_proxy_auth.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20100101 Firefox/11.0", - "proxy": "127.0.0.1:3038", - "proxy_auth": "user:pass", - "cache_ttl": 300, - "request_timeout": 60, - "connect_timeout": 10 -} diff --git a/spec/samples/empty-file b/spec/samples/empty-file deleted file mode 100644 index e69de29b..00000000 diff --git a/spec/samples/utf8.html b/spec/samples/utf8.html deleted file mode 100644 index cef71739..00000000 --- a/spec/samples/utf8.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - -明镜博客 - - - - - diff --git a/spec/samples/wpscan/web_site/has_log/matches.txt b/spec/samples/wpscan/web_site/has_log/matches.txt deleted file mode 100644 index edfa5b17..00000000 --- a/spec/samples/wpscan/web_site/has_log/matches.txt +++ /dev/null @@ -1,2 +0,0 @@ -[13-Jan-2009 01:53:25] PHP Fatal error: Class 'Log' not found in /home/****/public_html/wp-content/plugins/fbconnect/Log/null.php on line 19 -[13-Jan-2009 01:55:58] PHP Fatal error: Class 'Log' not found in /home/****/public_html/wp-content/plugins/fbconnect/Log/file.php on line 20 diff --git a/spec/samples/wpscan/web_site/has_log/matches_after_700_bytes.txt b/spec/samples/wpscan/web_site/has_log/matches_after_700_bytes.txt deleted file mode 100644 index 12f8ef7b..00000000 --- a/spec/samples/wpscan/web_site/has_log/matches_after_700_bytes.txt +++ /dev/null @@ -1,8 +0,0 @@ -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -[13-Jan-2009 01:53:25] PHP Fatal error: Class 'Log' not found in /home/****/public_html/wp-content/plugins/fbconnect/Log/null.php on line 19 diff --git a/spec/samples/wpscan/web_site/has_log/no_match.txt b/spec/samples/wpscan/web_site/has_log/no_match.txt deleted file mode 100644 index edbf8dcc..00000000 --- a/spec/samples/wpscan/web_site/has_log/no_match.txt +++ /dev/null @@ -1,3 +0,0 @@ -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -ccccccccccccccccccccccccccccccccc diff --git a/spec/samples/wpscan/web_site/robots_txt/empty_robots.txt b/spec/samples/wpscan/web_site/robots_txt/empty_robots.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/spec/samples/wpscan/web_site/robots_txt/invalid_robots.txt b/spec/samples/wpscan/web_site/robots_txt/invalid_robots.txt deleted file mode 100644 index f7bc0aa4..00000000 --- a/spec/samples/wpscan/web_site/robots_txt/invalid_robots.txt +++ /dev/null @@ -1,6 +0,0 @@ -ölhkdfys -opihufgcasfa -dsds -fsdf -s -dtf \ No newline at end of file diff --git a/spec/samples/wpscan/web_site/robots_txt/invalid_robots_2.txt b/spec/samples/wpscan/web_site/robots_txt/invalid_robots_2.txt deleted file mode 100644 index 19fa8dc5..00000000 --- a/spec/samples/wpscan/web_site/robots_txt/invalid_robots_2.txt +++ /dev/null @@ -1,8 +0,0 @@ -User-agent: * -Disallow: /wp-admin/ -Disallow: http://10.0.0.0/wp-includes/ -Disallow: wooooza -Disallow: /ÖÜ()=? -Allow: /asdf/ - -Sitemap: http://10.0.0.0/sitemap.xml.gz diff --git a/spec/samples/wpscan/web_site/robots_txt/robots.txt b/spec/samples/wpscan/web_site/robots_txt/robots.txt deleted file mode 100644 index 11d9942a..00000000 --- a/spec/samples/wpscan/web_site/robots_txt/robots.txt +++ /dev/null @@ -1,11 +0,0 @@ -User-agent: * -Disallow: /wp-admin/ -Disallow: /wp-includes/ -Disallow: /wordpress/admin/ -Disallow: /wordpress/wp-admin/ -Disallow: /wordpress/secret/ -Disallow: /Wordpress/wp-admin/ -Disallow: /wp-admin/tralling-space/ -Allow: /asdf/ - -Sitemap: http://10.0.0.0/sitemap.xml.gz diff --git a/spec/samples/wpscan/web_site/robots_txt/robots_duplicate_1.txt b/spec/samples/wpscan/web_site/robots_txt/robots_duplicate_1.txt deleted file mode 100644 index fe56eaf4..00000000 --- a/spec/samples/wpscan/web_site/robots_txt/robots_duplicate_1.txt +++ /dev/null @@ -1,17 +0,0 @@ -User-agent: * -Disallow: /wp-admin/ -Disallow: /wp-admin/ -Disallow: /wp-admin/ -Disallow: /wp-admin/ -Disallow: /wp-includes/ -Disallow: /wordpress/admin/ -Disallow: /wordpress/wp-admin/ -Disallow: /wordpress/secret/ -Disallow: /wordpress/secret/ -Disallow: /wordpress/ -Disallow: /wordpress/secret/ -Disallow: /Wordpress/wp-admin/ -Disallow: /wp-admin/tralling-space/ -Allow: /asdf/ - -Sitemap: http://10.0.0.0/sitemap.xml.gz diff --git a/spec/samples/wpscan/web_site/robots_txt/robots_duplicate_2.txt b/spec/samples/wpscan/web_site/robots_txt/robots_duplicate_2.txt deleted file mode 100644 index 91f19bfc..00000000 --- a/spec/samples/wpscan/web_site/robots_txt/robots_duplicate_2.txt +++ /dev/null @@ -1,9 +0,0 @@ -User-agent: * -Disallow: /wp-admin/ -Disallow: /wp-admin/ -Disallow: /wp-admin/ -Disallow: /wp-admin/ -Disallow: /wp-admin/ -Disallow: /wp-admin/ - -Sitemap: http://10.0.0.0/sitemap.xml.gz diff --git a/spec/samples/wpscan/web_site/rss_url/wordpress-3.5.htm b/spec/samples/wpscan/web_site/rss_url/wordpress-3.5.htm deleted file mode 100644 index aa68154c..00000000 --- a/spec/samples/wpscan/web_site/rss_url/wordpress-3.5.htm +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - -Wordpress 3.5 | Just another WordPress site - - - - - - - - - - - - - - - - - - - - - diff --git a/spec/samples/wpscan/web_site/xml_rpc_url/body_dont_match.html b/spec/samples/wpscan/web_site/xml_rpc_url/body_dont_match.html deleted file mode 100644 index b769e246..00000000 --- a/spec/samples/wpscan/web_site/xml_rpc_url/body_dont_match.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - -Wordpress 3.5.1 - - - - - - - - diff --git a/spec/samples/wpscan/web_site/xml_rpc_url/body_match.html b/spec/samples/wpscan/web_site/xml_rpc_url/body_match.html deleted file mode 100644 index 01ea1336..00000000 --- a/spec/samples/wpscan/web_site/xml_rpc_url/body_match.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - -Wordpress 3.5.1 - - - - - - - - - diff --git a/spec/samples/wpscan/wp_target/debug_log/debug-notice.log b/spec/samples/wpscan/wp_target/debug_log/debug-notice.log deleted file mode 100644 index 0e96ca47..00000000 --- a/spec/samples/wpscan/wp_target/debug_log/debug-notice.log +++ /dev/null @@ -1,2 +0,0 @@ -[11-Oct-2012 00:00:00] PHP Notice: Undefined index: ec_email in /var/www/wp/wp-content/plugins/easy-contact/econtact.php on line 33 -[11-Oct-2012 00:00:00] PHP Notice: Undefined index: ec_url in /var/www/wp/wp-content/plugins/easy-contact/econtact.php on line 34 diff --git a/spec/samples/wpscan/wp_target/debug_log/debug.log b/spec/samples/wpscan/wp_target/debug_log/debug.log deleted file mode 100644 index c8cd1314..00000000 --- a/spec/samples/wpscan/wp_target/debug_log/debug.log +++ /dev/null @@ -1 +0,0 @@ -[29-Jul-2012 13:12:16] PHP Warning: fopen(http://lamp/wordpress-3.4.1-custom/wp-cron.php?doing_wp_cron=1343567536.4001460075378417968750): failed to open stream: HTTP request failed! in /var/www/wordpress-3.4.1-custom/wp-includes/class-http.php on line 923 diff --git a/spec/samples/wpscan/wp_target/wp-login.php b/spec/samples/wpscan/wp_target/wp-login.php deleted file mode 100644 index 25d015e5..00000000 --- a/spec/samples/wpscan/wp_target/wp-login.php +++ /dev/null @@ -1,54 +0,0 @@ - - - - - Wordpress 3.3.2 › Log In - - - - - -

    Wordpress 3.3.2

    - -
    -

    - -

    -

    - -

    -

    -

    - - - -

    -
    - - - - - -

    ← Back to Wordpress 3.3.2

    -
    - - -
    - - diff --git a/spec/samples/wpscan/wp_target/wp_config_backup/wp-config.php b/spec/samples/wpscan/wp_target/wp_config_backup/wp-config.php deleted file mode 100644 index e47e1b5a..00000000 --- a/spec/samples/wpscan/wp_target/wp_config_backup/wp-config.php +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - diff --git a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-custom-subdirectories.htm b/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-custom-subdirectories.htm deleted file mode 100644 index ae2d1090..00000000 --- a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-custom-subdirectories.htm +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - -Wordpress 3.4.1 Custom | Just another WordPress site - - - - - - - - - - - - - - -
    - - - -
    - -
    -
    - - - - - - - - - - -
    -
    - - - -
    - - -
    - - - - diff --git a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-custom-with-spaces.htm b/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-custom-with-spaces.htm deleted file mode 100644 index b2f8f7dd..00000000 --- a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-custom-with-spaces.htm +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - -Wordpress 3.4.1 Custom | Just another WordPress site - - - - - - - - - - - - - - -
    - - - -
    - -
    -
    - - - - - - - - - - -
    -
    - - - -
    - - -
    - - - - diff --git a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-custom.htm b/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-custom.htm deleted file mode 100644 index 8feab76f..00000000 --- a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-custom.htm +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - -Wordpress 3.4.1 Custom | Just another WordPress site - - - - - - - - - - - - - - -
    - - - -
    - -
    -
    - - - - - - - - - - -
    -
    - - - -
    - - -
    - - - - \ No newline at end of file diff --git a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-in-plugins.htm b/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-in-plugins.htm deleted file mode 100644 index 029b688f..00000000 --- a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-in-plugins.htm +++ /dev/null @@ -1,8 +0,0 @@ - - - - - Hello - - - diff --git a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-in-src.htm b/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-in-src.htm deleted file mode 100644 index f439aea4..00000000 --- a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1-in-src.htm +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - -Wordpress 3.4.1 | Just another WordPress site - - - - - - - - - - - - - -
    - - - -
    - -
    -
    - - - - - - - - - - -
    -
    - - - -
    - - -
    - - - - diff --git a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1.htm b/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1.htm deleted file mode 100644 index 950b237f..00000000 --- a/spec/samples/wpscan/wp_target/wp_content_dir/wordpress-3.4.1.htm +++ /dev/null @@ -1,20 +0,0 @@ - - - - -Wordpress 3.4.1 | Just another WordPress site - - - - - - - - - - - - - diff --git a/spec/samples/wpscan/wp_target/wp_full_path_disclosure/rss-functions-disclosure.php b/spec/samples/wpscan/wp_target/wp_full_path_disclosure/rss-functions-disclosure.php deleted file mode 100644 index fd6ac74f..00000000 --- a/spec/samples/wpscan/wp_target/wp_full_path_disclosure/rss-functions-disclosure.php +++ /dev/null @@ -1,11 +0,0 @@ - -
    - - - - - -
    ( ! ) - Fatal error: Call to undefined function _deprecated_file() in -/home/web/www/blog/wordpress/wp-includes/rss-functions.php on line 8
    Call Stack
    #TimeMemoryFunctionLocation
    10.0000630936{main}( )../rss-functions.php:0
    - \ No newline at end of file diff --git a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-better_wp_security.php b/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-better_wp_security.php deleted file mode 100644 index e69de29b..00000000 diff --git a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-bluetrait_event_viewer.php b/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-bluetrait_event_viewer.php deleted file mode 100644 index e69de29b..00000000 diff --git a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-clean.php b/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-clean.php deleted file mode 100644 index 25d015e5..00000000 --- a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-clean.php +++ /dev/null @@ -1,54 +0,0 @@ - - - - - Wordpress 3.3.2 › Log In - - - - - -

    Wordpress 3.3.2

    - -
    -

    - -

    -

    - -

    -

    -

    - - - -

    -
    - - - - - -

    ← Back to Wordpress 3.3.2

    -
    - - -
    - - diff --git a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-limit_login_attempts.php b/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-limit_login_attempts.php deleted file mode 100644 index e69de29b..00000000 diff --git a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-login_lock.php b/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-login_lock.php deleted file mode 100644 index 043335a4..00000000 --- a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-login_lock.php +++ /dev/null @@ -1,54 +0,0 @@ - - - - - Wordpress 3.3.2 › Log In - - - - - -

    Wordpress 3.3.2

    - -
    -

    - -

    -

    - -

    -

    Site protected by LOGIN LOCK
    Strong WordPress Security

    -

    - - - -

    -
    - - - - - -

    ← Back to Wordpress 3.3.2

    -
    - - -
    - - diff --git a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-login_lockdown.php b/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-login_lockdown.php deleted file mode 100644 index d1eaa13f..00000000 --- a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-login_lockdown.php +++ /dev/null @@ -1,54 +0,0 @@ - - - - - Wordpress 3.3.2 › Log In - - - - - -

    Wordpress 3.3.2

    - -
    -

    - -

    -

    - -

    -

    Login form protected by Login LockDown.


    -

    - - - -

    -
    - - - - - -

    ← Back to Wordpress 3.3.2

    -
    - - -
    - - diff --git a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-login_security_solution.php b/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-login_security_solution.php deleted file mode 100644 index e69de29b..00000000 diff --git a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-security_protection.php b/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-security_protection.php deleted file mode 100644 index a12a0a02..00000000 --- a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-security_protection.php +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - WordPress 4.1 › Log In - - - - - - - - - - -
    -

    WordPress 4.1

    - -
    -

    - -

    -

    - -

    - -

    - - -

    -

    - - - -

    -
    - - - - - -

    ← Back to WordPress 4.1

    - -
    - - -
    - - - diff --git a/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-simple_login_lockdown.php b/spec/samples/wpscan/wp_target/wp_login_protection/wp-login-simple_login_lockdown.php deleted file mode 100644 index e69de29b..00000000 diff --git a/spec/samples/wpscan/wp_target/wp_readme/readme-3.2.1.html b/spec/samples/wpscan/wp_target/wp_readme/readme-3.2.1.html deleted file mode 100644 index 691753e2..00000000 --- a/spec/samples/wpscan/wp_target/wp_readme/readme-3.2.1.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - WordPress › ReadMe - - - -

    - WordPress -
    Version 3.2.1 -

    -

    Semantic Personal Publishing Platform

    - -

    First Things First

    -

    Welcome. WordPress is a very special project to me. Every developer and contributor adds something unique to the mix, and together we create something beautiful that I'm proud to be a part of. Thousands of hours have gone into WordPress, and we're dedicated to making it better every day. Thank you for making it part of your world.

    -

    — Matt Mullenweg

    - -

    Installation: Famous 5-minute install

    -
      -
    1. Unzip the package in an empty directory and upload everything.
    2. -
    3. Open wp-admin/install.php in your browser. It will take you through the process to set up a wp-config.php file with your database connection details. -
        -
      1. If for some reason this doesn't work, don't worry. It doesn't work on all web hosts. Open up wp-config-sample.php with a text editor like WordPad or similar and fill in your database connection details.
      2. -
      3. Save the file as wp-config.php and upload it.
      4. -
      5. Open wp-admin/install.php in your browser.
      6. -
      -
    4. -
    5. Once the configuration file is set up, the installer will set up the tables needed for your blog. If there is an error, double check your wp-config.php file, and try again. If it fails again, please go to the support forums with as much data as you can gather.
    6. -
    7. If you did not enter a password, note the password given to you. If you did not provide a username, it will be admin.
    8. -
    9. The installer should then send you to the login page. Sign in with the username and password you chose during the installation. If a password was generated for you, you can then click on 'Profile' to change the password.
    10. -
    - -

    Updating

    -

    Using the Automatic Updater

    -

    If you are updating from version 2.7 or higher, you can use the automatic updater:

    -
      -
    1. Open the wp-admin/update-core.php in your browser and follow the instructions.
    2. -
    3. You wanted more, perhaps? That's it!
    4. -
    - -

    Updating Manually

    -
      -
    1. Before you update anything, make sure you have backup copies of any files you may have modified such as index.php.
    2. -
    3. Delete your old WordPress files, saving ones you've modified.
    4. -
    5. Upload the new files.
    6. -
    7. Point your browser to /wp-admin/upgrade.php.
    8. -
    - -

    Theme Template Changes

    -

    If you have customized your theme templates, you may have to make some changes across major versions.

    - -

    Migrating from other systems

    -

    WordPress can import from a number of systems. First you need to get WordPress installed and working as described above, before using our import tools.

    - -

    System Requirements

    -
      -
    • PHP version 5.2.4 or higher.
    • -
    • MySQL version 5.0 or higher.
    • -
    - -

    System Recommendations

    - - -

    Online Resources

    -

    If you have any questions that aren't addressed in this document, please take advantage of WordPress' numerous online resources:

    -
    -
    The WordPress Codex
    -
    The Codex is the encyclopedia of all things WordPress. It is the most comprehensive source of information for WordPress available.
    -
    The WordPress Blog
    -
    This is where you'll find the latest updates and news related to WordPress. Recent WordPress news appears in your administrative dashboard by default.
    -
    WordPress Planet
    -
    The WordPress Planet is a news aggregator that brings together posts from WordPress blogs around the web.
    -
    WordPress Support Forums
    -
    If you've looked everywhere and still can't find an answer, the support forums are very active and have a large community ready to help. To help them help you be sure to use a descriptive thread title and describe your question in as much detail as possible.
    -
    WordPress IRC Channel
    -
    There is an online chat channel that is used for discussion among people who use WordPress and occasionally support topics. The above wiki page should point you in the right direction. (irc.freenode.net #wordpress)
    -
    - -

    XML-RPC and Atom Interface

    -

    You can post to your WordPress blog with tools like Windows Live Writer, Ecto, w.bloggar, Radio Userland (which means you can use Radio's email-to-blog feature), NewzCrawler, and other tools that support the blogging APIs! :) You can read more about XML-RPC support on the Codex.

    - -

    Post via Email

    -

    You can post from an email client! To set this up go to your "Writing" options screen and fill in the connection details for your secret POP3 account. Then you need to set up wp-mail.php to execute periodically to check the mailbox for new posts. You can do it with cron-jobs, or if your host doesn't support it you can look into the various website-monitoring services, and make them check your wp-mail.php URL.

    -

    Posting is easy: Any email sent to the address you specify will be posted, with the subject as the title. It is best to keep the address discrete. The script will delete emails that are successfully posted.

    - -

    User Roles

    -

    We introduced a very flexible roles system in version 2.0. You can read more about Roles and Capabilities on the Codex.

    - -

    Final Notes

    -
      -
    • If you have any suggestions, ideas, or comments, or if you (gasp!) found a bug, join us in the Support Forums.
    • -
    • WordPress has a robust plugin API that makes extending the code easy. If you are a developer interested in utilizing this, see the plugin documentation in the Codex. You shouldn't modify any of the core code.
    • -
    - -

    Share the Love

    -

    WordPress has no multi-million dollar marketing campaign or celebrity sponsors, but we do have something even better—you. If you enjoy WordPress please consider telling a friend, setting it up for someone less knowledgable than yourself, or writing the author of a media article that overlooks us.

    - -

    WordPress is the official continuation of b2/cafélog, which came from Michel V. The work has been continued by the WordPress developers. If you would like to support WordPress, please consider donating.

    - -

    License

    -

    WordPress is free software, and is released under the terms of the GPL version 2 or (at your option) any later version. See license.txt.

    - - - - diff --git a/spec/samples/wpscan/wp_target/wp_readme/readme-3.3.2-fr.html b/spec/samples/wpscan/wp_target/wp_readme/readme-3.3.2-fr.html deleted file mode 100644 index 1f8c0576..00000000 --- a/spec/samples/wpscan/wp_target/wp_readme/readme-3.3.2-fr.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - WordPress › À lire - - - -

    - WordPress -
    Version 3.3.1 - -

    -

    Plateforme de publication sémantique personnelle

    - -

    Préambule

    -

    Bienvenue. WordPress est un projet très spécial pour moi. Chaque développeur et contributeur ajoute quelque chose d'unique à ce projet, et ensemble nous créons quelque chose de beau, et dont je suis fier de faire partie. Nous avons passé des milliers d'heures sur le développement WordPress, et nous nous attachons tous les jours à vous faciliter la vie. Merci d'en faire une partie d'un morceau de votre monde.

    -

    — Matt Mullenweg

    - -

    Installation : la fameuse installation en 5 minutes

    -
      -
    1. Décompressez l'archive dans un dossier vide de votre ordinateur, puis mettez tous ces fichiers en ligne ;
    2. -
    3. Ouvrez le fichier wp-config-sample.php avec votre éditeur de texte préféré, comme WordPad ou similaire, et complétez les informations liées à votre base de données ;
    4. -
    5. Sauvegardez le fichier sous le nom wp-config.php ;
    6. -
    7. Envoyez le tout sur votre hébergement via un logiciel client FTP ;
    8. -
    9. Ouvrez le fichier /wp-admin/install.php dans votre navigateur. Celui-ci vous guidera dans la création du fichier wp-config.php, qui contient les détails de connexion à votre base de données ; -
        -
      1. Si cela ne marchait pas, ne vous inquietez pas : certains hébergeurs n'autorisent pas la création de fichier. Ouvrez le fichier wp-config.php avec un éditeur de texte, et saissez-y directement les détails de connexion à votre base de données ;
      2. -
      3. Enregistrez le fichier sous le nom wp-config.php et mettez-le en ligne ;
      4. -
      5. Ouvrez le fichier wp-admin/install.php dans votre navigateur ;
      6. -
      -
    10. -
    11. Une fois le fichier de configuration correctement rempli, l'installateur met en place les tables nécessaires à votre blog. Si vous obtenez une erreur, vérifiez le contenu du fichier wp-config.php, et réessayez. Si cela échoue encore une fois, rendez-vous sur les forums d'entraide et soyez le plus précis possible dans vos explications. Si tout se passe bien, passez à l'étape suivante ;
    12. -
    13. Si vous n'avez pas précisé de mot de passe, notez bien celui qui vous est donné. Si vous n'avez pas précisé d'identifiant utilisateur, ce sera admin ;
    14. -
    15. Une fois l'installation terminée, le script d'installation vous renverra vers la page de connexion. Connectez-vous avec l'identifiant et le mot de passe précisés (ou générés) durant l'installation. Si le mot de passe a été généré pour vous, cliquez sur "Profil" pour le modifier.
    16. -
    - -

    Mise à jour

    -

    A l'aide de l'outil de mise à jour automatique

    -

    Si votre version de WordPress est égale ou supérieure à 2.7, vous pouvez utiliser l'outil de mise à jour automatique :

    -
      -
    1. Ouvrez la page wp-admin/update-core.php dans votre navigateur, et suivez les instructions ;
    2. -
    3. Vous pensiez qu'il y aurai d'autres étapes ? C'est tout !
    4. -
    - -

    Mise à jour manuelle (obligatoire pour les versions de WordPress inférieures à 2.7) :

    -
      -
    1. Avant tout, assurez-vous bien de disposer de copies de sauvegarde de tous les fichiers que vous avez modifiés, par exemple index.php.
    2. -
    3. Effacez vos anciens fichiers WordPress, sauf ceux que vous avez modifié, comme wp-config.php ou le contenu du dossier /wp-content/.
    4. -
    5. Mettez en ligne les nouveaux fichiers en provenance de l'archive de WordPress.
    6. -
    7. Allez sur la page /wp-admin/upgrade.php avec votre navigateur internet.
    8. -
    - -

    Modification dans les thèmes

    -

    Si vous avez modifié votre thème, vous aurez probablement quelques modifications à faire

    - -

    Migrer depuis d'autres logiciels/plates-formes

    -

    WordPress peut importer les articles en provenance de nombreux autres outils (en). Vous devez d'abord installer WordPress comme expliqué plus haut, puis utiliser un des importateurs.

    - -

    Pré-requis fonctionnels

    -
      -
    • PHP version 5.2.4 ou plus ;
    • -
    • MySQL version 5.0 ou plus.
    • -
    - -

    Ressources en ligne

    -

    Si vous vous posez des questions dont les réponses ne figurent pas sur ce document, vous disposez de nombreuses ressources en ligne :

    -
    -
    Le Codex WordPress
    -
    Le Codex est l'encyclopédie liée à tout le fonctionnement de WordPress. Il s'agit de la source d'informations la plus complète qui soit.
    -
    Le blog de WordPress
    -
    C'est ici que vous trouverez les dernières informations, les annonces et les nouveautés de WordPress. Les derniers articles de ce blog sont affichés dans le Tableau de Bord de WordPress par défaut.
    -
    Planète WordPress
    -
    La Planète WordPress est un agrégateur de news qui distille les articles de plusieurs blogs WordPress à travers le web.
    -
    Support WordPress Francophone
    -
    Si vous avez cherché partout et que malgré cela vous n'avez trouvé aucune réponse, les forums sont très actifs et son immense communauté sera prête à vous aider. Pour un traitement efficace de votre problème, faites en sorte d'utiliser, lors de la création de votre sujet, un titre et une description aussi pertinents et clairs que possible.
    -
    Canal IRC WordPress
    -
    Il existe un canal IRC qui est le rendez-vous des utilisateurs WordPress, et occasionnellement, propose son aide aux sujets liés au support. La page Wiki devrait vous indiquer la bonne direction.
    -
    - -

    Interfaces XML-RPC et Atom

    -

    Il vous est possible d'écrire vos articles via des outils de publication comme Windows Live Writer, Ecto, Bloggar, Radio Userland (ce qui signifie que vous pouvez utiliser leur fonction "email-to-blog"), NewzCrawler, et d'autres outils qui utilisent les API de blog :) Pour en savoir davantage, rendez-vous sur la page du Codex expliquant le support XML-RPC (en).

    - -

    Publier par messagerie

    -

    Il vous est possible d'écrire directement vos articles à partir d'un logiciel de messagerie ! Pour cela, vous devez vous rendre sur la page d'options "Ecriture" et indiquer les détails de votre compte POP3 secret. Ensuite, vous devez faire en sorte que wp-mail.php s'exécute périodiquement, afin qu'il parcoure votre boite aux lettres à la recherche de nouveaux articles. Vous pouvez par exemple créer une tâche cron, ou si votre hébergeur ne supporte pas cette possibilité, il existe de nombreux sites proposant un service similaire de monitoring : il vous suffira d'indiquer l'adresse de votre fichier wp-mail.php

    -

    Publier devient facile : n'importe quel message envoyé à l'adresse que vous aurez précisée sera publié, le sujet du message étant le titre de l'article. Il est préférable de conserver cette adresse à l'abri des regards indiscrets. Le script effacera automatiquement les message qui auront été publiés avec succès

    - -

    Rôles d'utilisateurs

    -

    Nous avons mis en place un système de rôles très flexible dans la version 2.0. Référez-vous à la partie du codex expliquant les rôles et capacités des utilisateurs (en).

    - -

    Pour finir

    -
      -
    • Si vous avez des suggestions, des idées, des commentaires ou si (oups !) avez trouvé un bug, venez nous rejoindre sur les forums anglophones .
    • -
    • WordPress possède une API d'extension robuste, qui permet d'étendre les possibilités de son code de manière simple. Si vous êtes un développeur intéressé par son utilisation, rendez-vous sur la documentation des extensions sur le Codex. Vous ne devriez pas avoir à modifier une partie du code original.
    • -
    - -

    Faites connaître WordPress !

    -

    WordPress ne possède pas une kyrielle de millions de dollars pour s'offrir une campagne marketing, ni de célèbres sponsors, mais nous avons bien mieux : VOUS. Si vous appréciez WordPress, n'hésitez pas à en parler à votre entourage, vos amis, en aidant d'autres personnes ayant un niveau inférieur au vôtre, ou encore écrire un article faisant référence à notre travail.

    - -

    WordPress est la reprise officielle de b2/cafélog, provenant de Michel V. Le travail a continué d'être assuré par les développeurs WordPress. Si vous voulez apporter votre soutien à WordPress, n'hésitez pas à faire un don.

    - -

    Licence

    -

    WordPress est un logiciel libre, mis à disposition sous les termes de la licence GPL version 2, ou de toute version suivante, au choix (voir license.txt (en anglais)).

    - - - \ No newline at end of file diff --git a/spec/samples/wpscan/wp_target/xmlrpc.php b/spec/samples/wpscan/wp_target/xmlrpc.php deleted file mode 100644 index 3f908866..00000000 --- a/spec/samples/wpscan/wp_target/xmlrpc.php +++ /dev/null @@ -1 +0,0 @@ -XML-RPC server accepts POST requests only. \ No newline at end of file diff --git a/spec/samples/wpscan/wpscan_options/wordlist.txt b/spec/samples/wpscan/wpscan_options/wordlist.txt deleted file mode 100644 index 3f97879f..00000000 --- a/spec/samples/wpscan/wpscan_options/wordlist.txt +++ /dev/null @@ -1,4 +0,0 @@ -admin -1234 -root -toor diff --git a/spec/shared_examples/browser/actions.rb b/spec/shared_examples/browser/actions.rb deleted file mode 100644 index 376b91e6..00000000 --- a/spec/shared_examples/browser/actions.rb +++ /dev/null @@ -1,60 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'Browser::Actions' do - - describe '#post' do - it 'returns a Typhoeus::Response wth body = "Welcome Master" if login=master&password=itsme!' do - url = 'http://example.com/' - - stub_request(:post, url).with(body: { login: 'master', password: 'itsme!' }). - to_return(status: 200, body: 'Welcome Master') - - response = Browser.post( - url, - body: 'login=master&password=itsme!' - #body: { login: 'master', password: 'hello' } # It's should be this line, but it fails - ) - - expect(response).to be_a Typhoeus::Response - expect(response.body).to eq 'Welcome Master' - end - end - - describe '#get' do - it "returns a Typhoeus::Response with body = 'Hello World !'" do - url = 'http://example.com/' - - stub_request(:get, url). - to_return(status: 200, body: 'Hello World !') - - response = Browser.get(url) - - expect(response).to be_a Typhoeus::Response - expect(response.body).to eq 'Hello World !' - end - end - - describe '#get_and_follow_location' do - # Typhoeus does not follow the location with rspec - # See https://github.com/typhoeus/typhoeus/issues/279 - - #context 'whitout max_redirects params' do - # context 'when multiples redirection' do - # it 'returns the last redirection response' do - # url = 'http://target.com' - # first_redirection = 'www.first-redirection.com' - # last_redirection = 'last-redirection.com' - - # stub_request(:get, url).to_return(status: 301, headers: { location: first_redirection }) - # stub_request(:get, first_redirection).to_return(status: 301, headers: { location: last_redirection }) - # stub_request(:get, last_redirection).to_return(status: 200, body: 'Hello World!') - - # response = Browser.get_and_follow_location(url) - - # response.body.should === 'Hellow World!' - # end - # end - #end - end - -end diff --git a/spec/shared_examples/browser/options.rb b/spec/shared_examples/browser/options.rb deleted file mode 100644 index 010e0991..00000000 --- a/spec/shared_examples/browser/options.rb +++ /dev/null @@ -1,199 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'Browser::Options' do - - describe '#basic_auth=' do - let(:exception) { /^Invalid basic authentication format, "login:password" or "Basic base_64_encoded" expected. Your input: .+$/ } - - after do - if @expected - browser.basic_auth = @auth - expect(browser.basic_auth).to eq @expected - else - expect { browser.basic_auth = @auth }.to raise_error(RuntimeError, exception) - end - end - - context 'when invalid format' do - it 'raises an error' do - @auth = 'invalid' - end - end - - context 'when login:password' do - it 'sets the basic auth' do - @auth = 'admin:weakpass' - @expected = 'Basic YWRtaW46d2Vha3Bhc3M=' - end - end - - context 'when Basic base_64_encoded' do - context 'when invalid base_64_encoded' do - it 'raises an error' do - @auth = 'Basic ' - end - end - - it 'sets the basic auth' do - @auth = 'Basic dXNlcm5hbWU6dGhlYmlncGFzc3dvcmRzb3dlYWs=' - @expected = @auth - end - end - end - - describe '#max_threads= & #max_threads' do - let(:exception) { 'max_threads must be an Integer > 0' } - - after do - if @expected - browser.max_threads = @max_threads - expect(browser.max_threads).to eq @expected - else - expect { browser.max_threads = @max_threads }.to raise_error(exception) - end - end - - context 'when the argument is not an Integer > 0' do - it 'raises an error' do - @max_thrads = nil - end - - it 'raises an error' do - @max_threads = -3 - end - end - - context 'when the argument is an Integer' do - it 'returns the @max_threads' do - @max_threads = 10 - @expected = 10 - end - end - end - - describe 'proxy=' do - let(:exception) { 'Invalid proxy format. Should be [protocol://]host:port.' } - - after do - if @expected - browser.proxy = @proxy - expect(browser.proxy).to eq @expected - else - expect { browser.proxy = @proxy }.to raise_error(exception) - end - end - - context 'when invalid format' do - it 'raises an error' do - @proxy = 'yolo' - end - end - - context 'when valid format' do - @proxy = '127.0.0.1:9050' - @expected = @proxy - end - end - - describe 'proxy_auth=' do - let(:exception) { 'Invalid proxy auth format, expected username:password or {proxy_username: username, proxy_password: password}' } - - after :each do - if @expected - browser.proxy_auth = @proxy_auth - expect(browser.proxy_auth).to be === @expected - else - expect { browser.proxy_auth = @proxy_auth }.to raise_error - end - end - - context 'when the auth supplied is' do - context 'not a String or a Hash' do - it 'raises an error' do - @proxy_auth = 10 - end - end - - context 'a String with' do - context 'invalid format' do - it 'raises an error' do - @proxy_auth = 'invaludauthformat' - end - end - - context 'valid format' do - it 'sets the auth' do - @proxy_auth = 'username:passwd' - @expected = @proxy_auth - end - end - end - - context 'a Hash with' do - context 'only :proxy_username' do - it 'raises an error' do - @proxy_auth = { proxy_username: 'username' } - end - end - - context 'only :proxy_password' do - it 'raises an error' do - @proxy_auth = { proxy_password: 'hello' } - end - end - - context ':proxy_username and :proxy_password' do - it 'sets the auth' do - @proxy_auth = { proxy_username: 'user', proxy_password: 'pass' } - @expected = 'user:pass' - end - end - end - end - end - - describe '#override_config' do - after do - browser.send(:override_config, override_options) - end - - let(:config) { JSON.parse(File.read(browser.config_file)) } - - context 'when an option value is nil' do - let(:override_options) { { max_threads: nil } } - - it 'does not set it' do - expect(browser).not_to receive(:max_threads=) - end - end - - context 'when an option is no allowed' do - let(:override_options) { { not_allowed: 'owned' } } - - it 'does not set it' do - expect(browser).not_to receive(:not_allowed=) - end - end - - context 'when valid option' do - let(:override_options) { { max_threads: 30 } } - - it 'sets it' do - expect(browser).to receive(:max_threads=).with(30) - end - end - - context 'when multiple options' do - let(:override_options) { - { max_threads: 10, not_allowed: 'owned', proxy: 'host:port' } - } - - it 'sets @max_threads, @proxy' do - expect(browser).not_to receive(:not_allowed=) - expect(browser).to receive(:max_threads=).with(10) - expect(browser).to receive(:proxy=).with('host:port') - end - end - end - -end diff --git a/spec/shared_examples/web_site/humans_txt.rb b/spec/shared_examples/web_site/humans_txt.rb deleted file mode 100644 index b54d1ed5..00000000 --- a/spec/shared_examples/web_site/humans_txt.rb +++ /dev/null @@ -1,108 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WebSite::HumansTxt' do - let(:known_dirs) { WebSite::HumansTxt.known_dirs } - - describe '#humans_url' do - it 'returns the correct url' do - expect(web_site.humans_url).to eql 'http://example.localhost/humans.txt' - end - end - - describe '#has_humans?' do - it 'returns true' do - stub_request(:get, web_site.humans_url).to_return(status: 200) - expect(web_site.has_humans?).to be_truthy - end - - it 'returns false' do - stub_request(:get, web_site.humans_url).to_return(status: 404) - expect(web_site.has_humans?).to be_falsey - end - end - - describe '#parse_humans_txt' do - - context 'installed in root' do - after :each do - stub_request_to_fixture(url: web_site.humans_url, fixture: @fixture) - humans = web_site.parse_humans_txt - expect(humans).to match_array @expected - end - - it 'returns an empty Array (empty humans.txt)' do - @fixture = fixtures_dir + '/humans_txt/empty_humans.txt' - @expected = [] - end - - it 'returns an empty Array (invalid humans.txt)' do - @fixture = fixtures_dir + '/humans_txt/invalid_humans.txt' - @expected = [] - end - - it 'returns some urls and some strings' do - @fixture = fixtures_dir + '/humans_txt/invalid_humans_2.txt' - @expected = %w( - /ÖÜ()=? - http://10.0.0.0/wp-includes/ - http://example.localhost/asdf/ - wooooza - ) - end - - it 'returns an Array of urls (valid humans.txt)' do - @fixture = fixtures_dir + '/humans_txt/humans.txt' - @expected = %w( - http://example.localhost/wordpress/admin/ - http://example.localhost/wordpress/wp-admin/ - http://example.localhost/wordpress/secret/ - http://example.localhost/Wordpress/wp-admin/ - http://example.localhost/wp-admin/tralling-space/ - http://example.localhost/asdf/ - ) - end - - it 'removes duplicate entries from humans.txt test 1' do - @fixture = fixtures_dir + '/humans_txt/humans_duplicate_1.txt' - @expected = %w( - http://example.localhost/wordpress/ - http://example.localhost/wordpress/admin/ - http://example.localhost/wordpress/wp-admin/ - http://example.localhost/wordpress/secret/ - http://example.localhost/Wordpress/wp-admin/ - http://example.localhost/wp-admin/tralling-space/ - http://example.localhost/asdf/ - ) - end - - it 'removes duplicate entries from humans.txt test 2' do - @fixture = fixtures_dir + '/humans_txt/humans_duplicate_2.txt' - @expected = nil - end - end - - context 'installed in sub directory' do - it 'returns an Array of urls (valid humans.txt, WP installed in subdir)' do - web_site_sub = WebSite.new('http://example.localhost/wordpress/') - fixture = fixtures_dir + '/humans_txt/humans.txt' - expected = %w( - http://example.localhost/wordpress/admin/ - http://example.localhost/wordpress/secret/ - http://example.localhost/Wordpress/wp-admin/ - http://example.localhost/wp-admin/tralling-space/ - http://example.localhost/asdf/ - ) - stub_request_to_fixture(url: web_site_sub.humans_url, fixture: fixture) - humans = web_site_sub.parse_humans_txt - expect(humans).to match_array expected - end - end - end - - describe '#known_dirs' do - it 'does not contain duplicates' do - expect(known_dirs.flatten.uniq.length).to eq known_dirs.length - end - end - -end diff --git a/spec/shared_examples/web_site/interesting_headers.rb b/spec/shared_examples/web_site/interesting_headers.rb deleted file mode 100644 index 2ad92586..00000000 --- a/spec/shared_examples/web_site/interesting_headers.rb +++ /dev/null @@ -1,35 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WebSite::InterestingHeaders' do - - let(:known_headers) { WebSite::InterestingHeaders.known_headers } - - describe '#interesting_headers' do - - it 'returns MyTestHeader' do - stub_request(:head, web_site.url). - to_return(status: 200, headers: { 'Mytestheader' => 'Mytestheadervalue' }) - expect(web_site.interesting_headers).to match_array [ [ 'MYTESTHEADER', 'Mytestheadervalue' ] ] - end - - it 'removes known headers' do - stub_request(:head, web_site.url). - to_return(status: 200, headers: { 'Location' => 'a', 'Connection' => 'Close' }) - expect(web_site.interesting_headers).to be_empty - end - - it 'returns nothing' do - stub_request(:head, web_site.url). - to_return(status: 200, headers: { }) - expect(web_site.interesting_headers).to be_empty - end - - end - - describe '#known_headers' do - it 'does not contain duplicates' do - expect(known_headers.flatten.uniq.length).to eq known_headers.length - end - end - -end diff --git a/spec/shared_examples/web_site/robots_txt.rb b/spec/shared_examples/web_site/robots_txt.rb deleted file mode 100644 index 252762ab..00000000 --- a/spec/shared_examples/web_site/robots_txt.rb +++ /dev/null @@ -1,108 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WebSite::RobotsTxt' do - let(:known_dirs) { WebSite::RobotsTxt.known_dirs } - - describe '#robots_url' do - it 'returns the correct url' do - expect(web_site.robots_url).to eql 'http://example.localhost/robots.txt' - end - end - - describe '#has_robots?' do - it 'returns true' do - stub_request(:get, web_site.robots_url).to_return(status: 200) - expect(web_site.has_robots?).to be_truthy - end - - it 'returns false' do - stub_request(:get, web_site.robots_url).to_return(status: 404) - expect(web_site.has_robots?).to be_falsey - end - end - - describe '#parse_robots_txt' do - - context 'installed in root' do - after :each do - stub_request_to_fixture(url: web_site.robots_url, fixture: @fixture) - robots = web_site.parse_robots_txt - expect(robots).to match_array @expected - end - - it 'returns an empty Array (empty robots.txt)' do - @fixture = fixtures_dir + '/robots_txt/empty_robots.txt' - @expected = [] - end - - it 'returns an empty Array (invalid robots.txt)' do - @fixture = fixtures_dir + '/robots_txt/invalid_robots.txt' - @expected = [] - end - - it 'returns some urls and some strings' do - @fixture = fixtures_dir + '/robots_txt/invalid_robots_2.txt' - @expected = %w( - /ÖÜ()=? - http://10.0.0.0/wp-includes/ - http://example.localhost/asdf/ - wooooza - ) - end - - it 'returns an Array of urls (valid robots.txt)' do - @fixture = fixtures_dir + '/robots_txt/robots.txt' - @expected = %w( - http://example.localhost/wordpress/admin/ - http://example.localhost/wordpress/wp-admin/ - http://example.localhost/wordpress/secret/ - http://example.localhost/Wordpress/wp-admin/ - http://example.localhost/wp-admin/tralling-space/ - http://example.localhost/asdf/ - ) - end - - it 'removes duplicate entries from robots.txt test 1' do - @fixture = fixtures_dir + '/robots_txt/robots_duplicate_1.txt' - @expected = %w( - http://example.localhost/wordpress/ - http://example.localhost/wordpress/admin/ - http://example.localhost/wordpress/wp-admin/ - http://example.localhost/wordpress/secret/ - http://example.localhost/Wordpress/wp-admin/ - http://example.localhost/wp-admin/tralling-space/ - http://example.localhost/asdf/ - ) - end - - it 'removes duplicate entries from robots.txt test 2' do - @fixture = fixtures_dir + '/robots_txt/robots_duplicate_2.txt' - @expected = nil - end - end - - context 'installed in sub directory' do - it 'returns an Array of urls (valid robots.txt, WP installed in subdir)' do - web_site_sub = WebSite.new('http://example.localhost/wordpress/') - fixture = fixtures_dir + '/robots_txt/robots.txt' - expected = %w( - http://example.localhost/wordpress/admin/ - http://example.localhost/wordpress/secret/ - http://example.localhost/Wordpress/wp-admin/ - http://example.localhost/wp-admin/tralling-space/ - http://example.localhost/asdf/ - ) - stub_request_to_fixture(url: web_site_sub.robots_url, fixture: fixture) - robots = web_site_sub.parse_robots_txt - expect(robots).to match_array expected - end - end - end - - describe '#known_dirs' do - it 'does not contain duplicates' do - expect(known_dirs.flatten.uniq.length).to eq known_dirs.length - end - end - -end diff --git a/spec/shared_examples/web_site/security_txt.rb b/spec/shared_examples/web_site/security_txt.rb deleted file mode 100644 index 3bca86dd..00000000 --- a/spec/shared_examples/web_site/security_txt.rb +++ /dev/null @@ -1,108 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WebSite::SecurityTxt' do - let(:known_dirs) { WebSite::SecurityTxt.known_dirs } - - describe '#security_url' do - it 'returns the correct url' do - expect(web_site.security_url).to eql 'http://example.localhost/security.txt' - end - end - - describe '#has_security?' do - it 'returns true' do - stub_request(:get, web_site.security_url).to_return(status: 200) - expect(web_site.has_security?).to be_truthy - end - - it 'returns false' do - stub_request(:get, web_site.security_url).to_return(status: 404) - expect(web_site.has_security?).to be_falsey - end - end - - describe '#parse_security_txt' do - - context 'installed in root' do - after :each do - stub_request_to_fixture(url: web_site.security_url, fixture: @fixture) - security = web_site.parse_security_txt - expect(security).to match_array @expected - end - - it 'returns an empty Array (empty security.txt)' do - @fixture = fixtures_dir + '/security_txt/empty_security.txt' - @expected = [] - end - - it 'returns an empty Array (invalid security.txt)' do - @fixture = fixtures_dir + '/security_txt/invalid_security.txt' - @expected = [] - end - - it 'returns some urls and some strings' do - @fixture = fixtures_dir + '/security_txt/invalid_security_2.txt' - @expected = %w( - /ÖÜ()=? - http://10.0.0.0/wp-includes/ - http://example.localhost/asdf/ - wooooza - ) - end - - it 'returns an Array of urls (valid security.txt)' do - @fixture = fixtures_dir + '/security_txt/security.txt' - @expected = %w( - http://example.localhost/wordpress/admin/ - http://example.localhost/wordpress/wp-admin/ - http://example.localhost/wordpress/secret/ - http://example.localhost/Wordpress/wp-admin/ - http://example.localhost/wp-admin/tralling-space/ - http://example.localhost/asdf/ - ) - end - - it 'removes duplicate entries from security.txt test 1' do - @fixture = fixtures_dir + '/security_txt/security_duplicate_1.txt' - @expected = %w( - http://example.localhost/wordpress/ - http://example.localhost/wordpress/admin/ - http://example.localhost/wordpress/wp-admin/ - http://example.localhost/wordpress/secret/ - http://example.localhost/Wordpress/wp-admin/ - http://example.localhost/wp-admin/tralling-space/ - http://example.localhost/asdf/ - ) - end - - it 'removes duplicate entries from security.txt test 2' do - @fixture = fixtures_dir + '/security_txt/security_duplicate_2.txt' - @expected = nil - end - end - - context 'installed in sub directory' do - it 'returns an Array of urls (valid security.txt, WP installed in subdir)' do - web_site_sub = WebSite.new('http://example.localhost/wordpress/') - fixture = fixtures_dir + '/security_txt/security.txt' - expected = %w( - http://example.localhost/wordpress/admin/ - http://example.localhost/wordpress/secret/ - http://example.localhost/Wordpress/wp-admin/ - http://example.localhost/wp-admin/tralling-space/ - http://example.localhost/asdf/ - ) - stub_request_to_fixture(url: web_site_sub.security_url, fixture: fixture) - security = web_site_sub.parse_security_txt - expect(security).to match_array expected - end - end - end - - describe '#known_dirs' do - it 'does not contain duplicates' do - expect(known_dirs.flatten.uniq.length).to eq known_dirs.length - end - end - -end diff --git a/spec/shared_examples/wp_item_existable.rb b/spec/shared_examples/wp_item_existable.rb deleted file mode 100644 index e1f1c897..00000000 --- a/spec/shared_examples/wp_item_existable.rb +++ /dev/null @@ -1,94 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpItem::Existable' do - let(:fixtures_dir) { MODELS_FIXTURES + '/wp_item/existable' } - - describe '#exists?' do - context 'when the response is supplied' do - let(:response) { Typhoeus::Response.new } - - it 'does not create a request' do - expect(Browser).not_to receive(:get) - allow(subject).to receive(:exists_from_response?).and_return(true) - - expect(subject.exists?({}, response)).to be_truthy - end - end - - context 'when the response is not supplied' do - it 'creates a request' do - expect(Browser).to receive(:get) - allow(subject).to receive(:exists_from_response?).and_return(false) - - expect(subject.exists?).to be_falsey - end - end - end - - describe '#exists_from_response?' do - let(:exists_options) { {} } - let(:body) { 'hello world!' } - - after do - response = Typhoeus::Response.new(@resp_opt) - expect(subject.send(:exists_from_response?, response, exists_options)).to eq @expected - end - - context 'when invalid response.code' do - it 'returns false' do - @resp_opt = { code: 500 } - @expected = false - end - end - - context 'when the body hash = homepage_hash or error_404_hash' do - let(:exists_options) { { homepage_hash: Digest::MD5.hexdigest(body) } } - - it 'returns false' do - @resp_opt = { code: 200, body: body } - @expected = false - end - end - - context 'w/o exclude_content' do - [200, 401, 403].each do |code| - it "returns true on #{code}" do - @resp_opt = { code: code, body: '' } - @expected = true - end - end - end - - context 'with exclude_content' do - let(:exists_options) { { exclude_content: %r{world!} } } - - context 'when the body match' do - it 'returns false' do - @resp_opt = { code: 200, body: body } - @expected = false - end - end - - context 'when the body does not match' do - it 'returns true' do - @resp_opt = { code: 200, body: 'hello dude!' } - @expected = true - end - end - end - - context 'when it\'s a redirect to the homepage' do - context 'and the cache generation time is in comment tag' do - let(:body) { File.new(fixtures_dir + '/cache_generation.html').read } - let(:uncommented_body) { body.gsub(//m, '') } - let(:exists_options) { { homepage_hash: Digest::MD5.hexdigest(uncommented_body) } } - - it 'returns false' do - @resp_opt = { code: 200, body: body } - @expected = false - end - end - end - end - -end diff --git a/spec/shared_examples/wp_item_findable_found_from.rb b/spec/shared_examples/wp_item_findable_found_from.rb deleted file mode 100644 index 14ea7388..00000000 --- a/spec/shared_examples/wp_item_findable_found_from.rb +++ /dev/null @@ -1,17 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpItem::Findable#Found_From=' do - - describe '#found_from=' do - after do - subject.found_from = @method - expect(subject.found_from).to eq @expected - end - - it 'replaces _ by space' do - @method = 'find_from_some_detection_method' - @expected = 'some detection method' - end - end - -end diff --git a/spec/shared_examples/wp_item_infos.rb b/spec/shared_examples/wp_item_infos.rb deleted file mode 100644 index dd83ca89..00000000 --- a/spec/shared_examples/wp_item_infos.rb +++ /dev/null @@ -1,142 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpItem::Infos' do - - # 2 expected urls have to be set in the described class (or subject) - # e.g : - # let(:changelog_url) { } - # let(:error_log_url) { } - - describe '#readme_url' do - after { expect(subject.readme_url).to eql @expected } - - it 'returns nil' do - stub_request(:get, /.*/).to_return(status: 404) - @expected = nil - end - - context 'when the file exists' do - %w{readme.txt readme.md}.each do |readme| - it 'returns the correct url' do - url = uri.merge(readme).to_s - @expected = url - - stub_request(:get, %r{^(?!#{url})}).to_return(status: 404) - stub_request(:get, url).to_return(status: 200) - end - end - end - end - - describe '#has_readme?' do - after do - allow(subject).to receive_messages(readme_url: @stub) - expect(subject.has_readme?).to eql @expected - end - - context 'when readme_url is nil' - it 'returns false' do - @stub = nil - @expected = false - end - - context 'when readme_url is not nil' - it 'returns true' do - @stub = uri.merge('readme.txt').to_s - @expected = true - end - end - - describe '#changelog_url' do - after { expect(subject.changelog_url).to eql @expected } - - it 'returns nil' do - stub_request(:get, /.*/).to_return(status: 404) - @expected = nil - end - - context 'when the file exists' do - %w{changelog.txt CHANGELOG.md}.each do |changelog| - it 'returns the correct url' do - url = uri.merge(changelog).to_s - @expected = url - - stub_request(:get, %r{^(?!#{url})}).to_return(status: 404) - stub_request(:get, url).to_return(status: 200) - end - end - end - end - - describe '#has_changelog?' do - after do - allow(subject).to receive_messages(changelog_url: @stub) - expect(subject.has_changelog?).to eql @expected - end - - context 'when changelog_url is nil' - it 'returns false' do - @stub = nil - @expected = false - end - - context 'when changelog_url is not nil' - it 'returns true' do - @stub = uri.merge('changelog.txt').to_s - @expected = true - end - end - - describe '#has_directory_listing?' do - after do - stub_request(:get, subject.uri.to_s).to_return(@stub_return) - expect(subject.has_directory_listing?).to eql @expected - end - - context 'when the body contains Index of' do - it 'returns true' do - @stub_return = { status: 200, body: '<title>Index of asdf' } - @expected = true - end - end - - it 'returns false otherwise' do - @stub_return = { status: 200, body: 'My Wordpress Site' } - @expected = false - end - - it 'returns false on a 404' do - @stub_return = { status: 404 } - @expected = false - end - end - - describe '#error_log_url' do - it 'returns the correct url' do - expect(subject.error_log_url).to eq error_log_url - end - end - - describe '#has_error_log?' do - after do - stub_request(:get, subject.error_log_url).to_return(@stub_return) - expect(subject.has_error_log?).to eql @expected - end - - it 'returns true if the pattern is detected' do - @stub_return = { status: 200, body: File.new(MODELS_FIXTURES + '/wp_item/error_log') } - @expected = true - end - - it 'returns false otherwise' do - @stub_return = { status: 200, body: 'yolo' } - @expected = false - end - - it 'returns false on a 404' do - @stub_return = { status: 404 } - @expected = false - end - end - -end diff --git a/spec/shared_examples/wp_item_versionable.rb b/spec/shared_examples/wp_item_versionable.rb deleted file mode 100644 index d488231d..00000000 --- a/spec/shared_examples/wp_item_versionable.rb +++ /dev/null @@ -1,175 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpItem::Versionable' do - - describe '#version' do - let(:fixtures_dir) { MODELS_FIXTURES + '/wp_item/versionable' } - let(:readme_url) { subject.uri.merge('readme.txt').to_s } - - context 'when the version is already set' do - it 'returns it' do - subject.version = '1.2' - expect(subject.version).to eq '1.2' - end - end - - context 'otherwise' do - after do - stub_request_to_fixture(url: readme_url, fixture: fixtures_dir + @file) - expect(subject.version).to eq @expected - end - - context 'when version is "trunk"' do - it 'returns nil' do - @file = '/trunk-version.txt' - @expected = nil - end - end - - context 'when the version is valid' do - context 'when leaked from the stable tag' do - it 'returns it' do - @file = '/simple-login-lockdown-0.4.txt' - @expected = '0.4' - end - end - - context 'when leaked from the version' do - it 'returns it' do - @file = '/wp-photo-plus-5.1.15.txt' - @expected = '5.1.15' - end - end - - context 'when version is in a release date format' do - it 'detects and returns it' do - @file = '/s2member.txt' - @expected = '141007' - end - end - - context 'when version contains letters' do - it 'returns it' do - @file = '/beta1.txt' - @expected = '2.0.0-beta1' - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/changelog_version.txt' - @expected = '1.3' - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/wp_polls.txt' - @expected = '2.64' - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/nextgen_gallery.txt' - @expected = '2.0.66.33' - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/wp_user_frontend.txt' - @expected = '1.2.3' - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/my_calendar.txt' - @expected = '2.1.5' - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/nextgen_gallery_2.txt' - @expected = '1.9.13' - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/advanced-most-recent-posts-mod.txt' - @expected = '1.6.5.2' - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/a-lead-capture-contact-form-and-tab-button-by-awebvoicecom.txt' - @expected = '3.1' - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/aa-health-calculator.txt' - @expected = nil - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/all-in-one-facebook.txt' - @expected = nil - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/backup-scheduler.txt' - @expected = '1.5.9' - end - end - - context 'when parsing the changelog for version numbers' do - it 'returns it' do - @file = '/blog-reordering.txt' - @expected = nil - end - end - - # context 'when parsing the changelog for version numbers with dates' do - # it 'returns it' do - # @file = '/wp-maintenance-mode.txt' - # @expected = '2.0.9' - # end - # end - end - end - end - - describe '#to_s' do - after do - allow(subject).to receive(:version).and_return(@version) - subject.name = 'some-name' - - expect(subject.to_s).to eq @expected - end - - context 'when the version does not exist' do - it 'returns only the name' do - @version = nil - @expected = 'some-name' - end - end - - context 'when the version exists' do - it 'returns the name and the version' do - @version = '1.3' - @expected = 'some-name - v1.3' - end - end - end - -end diff --git a/spec/shared_examples/wp_item_vulnerable.rb b/spec/shared_examples/wp_item_vulnerable.rb deleted file mode 100644 index d582ac5e..00000000 --- a/spec/shared_examples/wp_item_vulnerable.rb +++ /dev/null @@ -1,109 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpItem::Vulnerable' do - - # 2 variables have to be set in the described class or subject: - # let(:db_file) { } - # let(:expected_vulns) { } The expected Vulnerabilities when using db_file and vulns_xpath - # - # 1 variable is optional, used if supplied, otherwise subject.vulns_xpath is used - # let(:vulns_xpath) { } - - describe '#vulnerabilities' do - let(:empty_file) { MODELS_FIXTURES + '/wp_item/vulnerable/empty.json' } - - before do - stub_request(:get, /.*\/readme\.(?:txt|md)/i) - stub_request(:get, /.*\/style\.css/i) - end - - after do - subject.db_file = @db_file - subject.identifier = identifier if defined?(identifier) - - result = subject.vulnerabilities - expect(result).to be_a Vulnerabilities - expect(result).to eq @expected - end - - context 'when the db_file is empty' do - it 'returns an empty Vulnerabilities' do - @db_file = empty_file - @expected = Vulnerabilities.new - end - end - - it 'returns the expected vulnerabilities' do - @db_file = db_file - @expected = expected_vulns - end - end - - describe '#vulnerable?' do - after do - allow(subject).to receive(:vulnerabilities).and_return(@stub) - expect(subject.vulnerable?).to eq @expected - end - - it 'returns false when no vulnerabilities' do - @stub = [] - @expected = false - end - - it 'returns true when vulnerabilities' do - @stub = ['not empty'] - @expected = true - end - end - - describe '#vulnerable_to?' do - let(:version_orig) { '1.5.6' } - let(:version_newer) { '1.6' } - let(:version_older) { '1.0' } - let(:newer) { Vulnerability.new('Newer', 'XSS', { :url => ['http://ref.com'] }, version_newer) } - let(:older) { Vulnerability.new('Older', 'XSS', { :url => ['http://ref.com'] }, version_older) } - let(:same) { Vulnerability.new('Same', 'XSS', { :url => ['http://ref.com'] }, version_orig) } - let(:no_fixed_info) { Vulnerability.new('Same', 'XSS', { :url => ['http://ref.com'] }, nil) } - - before do - stub_request(:get, /.*\/readme\.txt/i).to_return(status: 200, body: "Stable Tag: #{version_orig}") - stub_request(:get, /.*\/style\.css/i).to_return(status: 200, body: "Version: #{version_orig}") - end - - context 'check basic version comparing' do - it 'returns true because checked version is newer' do - expect(subject.version).to eq version_orig - expect(subject.vulnerable_to?(newer)).to be_truthy - end - - it 'returns false because checked version is older' do - expect(subject.version).to eq version_orig - expect(subject.vulnerable_to?(older)).to be_falsey - end - - it 'returns false because checked version is the fixed version' do - expect(subject.version).to eq version_orig - expect(subject.vulnerable_to?(same)).to be_falsey - end - - it 'returns true because no fixed_in version is provided' do - expect(subject.version).to eq version_orig - expect(subject.vulnerable_to?(no_fixed_info)).to be_truthy - end - end - - context 'no version found in wp_item' do - before do - stub_request(:get, /.*\/readme\.(?:txt|md)/i).to_return(status: 404) - stub_request(:get, /.*\/style\.css/i).to_return(status: 404) - end - - it 'returns true because no version can be detected' do - expect(subject.vulnerable_to?(newer)).to be_truthy - expect(subject.vulnerable_to?(older)).to be_truthy - expect(subject.vulnerable_to?(same)).to be_truthy - end - end - end - -end diff --git a/spec/shared_examples/wp_items_detectable.rb b/spec/shared_examples/wp_items_detectable.rb deleted file mode 100644 index 883f4a80..00000000 --- a/spec/shared_examples/wp_items_detectable.rb +++ /dev/null @@ -1,160 +0,0 @@ -# encoding: UTF-8 - -require WPSCAN_LIB_DIR + '/wp_target' - -shared_examples 'WpItems::Detectable' do - let(:vulns_file) { fixtures_dir + '/vulns.json' } - let(:targets_items_file) { fixtures_dir + '/targets.txt' } - let(:wp_content_dir) { 'wp-content' } - let(:wp_plugins_dir) { wp_content_dir + '/plugins' } - let(:wp_target) { WpTarget.new(url, wp_content_dir: wp_content_dir, wp_plugins_dir: wp_plugins_dir) } - let(:url) { 'http://example.com/' } - let(:uri) { URI.parse(url) } - let(:empty_file) { SPEC_FIXTURES_DIR + '/empty-file' } - - before do - if class_vulns_file = subject.vulns_file - expect(class_vulns_file).to eq expected[:vulns_file] - end - - allow(subject).to receive(:vulns_file).and_return(vulns_file) - - unless subject.item_xpath - allow(subject).to receive(:item_xpath).and_return('//item') - end - end - - describe '::request_params' do - it 'returns the default params' do - expect(subject.send(:request_params)).to eq expected[:request_params] - end - end - - describe '::item_class' do - it 'returns the correct item class' do - klass = subject.send(:item_class) - - expect(klass).to be_a Class - expect(klass).to eq item_class - end - end - - describe '::targets_items' do - let(:options) { { type: :all } } - - after do - if @expected - results = subject.send(:targets_items, wp_target, options) - - expect(results.sort.map { |i| i.name }).to eq @expected.sort.map { |i| i.name } - end - end - - context 'when :type = :vulnerable' do - let(:options) { { type: :vulnerable } } - - it 'returns the expected Array of WpItem' do - @expected = expected[:vulnerable_targets_items] - end - end - end - - describe '::passive_detection' do - after do - stub_request_to_fixture(url: wp_target.url, fixture: @fixture) - - results = subject.passive_detection(wp_target) - - expect(results).to be_a subject - expect(results.map { |i| i.name }).to eq @expected.sort.map { |i| i.name } - end - - context 'when the page is empty' do - it 'return an empty WpItems' do - @fixture = empty_file - @expected = subject.new - end - end - - context 'when items are present' do - it 'returns the expected items' do - @fixture = fixtures_dir + '/passive_detection.html' - @expected = expected[:passive_detection] - end - end - end - - describe '::aggressive_detection' do - def stub_targets_dont_exist(targets) - targets.each { |t| allow(t).to receive(:exists?).and_return(false) } - end - - let(:options) { {} } - - after do - stub_request(:get, /.*/).to_return(status: 404) - - result = subject.aggressive_detection(wp_target, options) - - expect(result).to be_a subject - expect(result.sort.map { |i| i.name }).to eq @expected.sort.map { |i| i.name } - end - - context 'when :type = :vulnerable' do - let(:options) { { type: :vulnerable } } - let(:targets) { expected[:vulnerable_targets_items] } - - it 'only checks and return vulnerable targets' do - samples = targets.sample(2) - fixed_target = samples[0] - vulnerable_target = samples[1] - - stub_targets_dont_exist(targets) - - allow(vulnerable_target).to receive(:exists?).and_return(true) - allow(vulnerable_target).to receive(:vulnerable?).and_return(true) - - allow(fixed_target).to receive(:exists?).and_return(true) - allow(fixed_target).to receive(:vulnerable?).and_return(false) - - @expected = subject.new << vulnerable_target - - expect(subject).to receive(:targets_items).and_return(targets) - end - - context 'when all targets dont exist' do - it 'returns an empty WpItems' do - stub_targets_dont_exist(targets) - expect(subject).to receive(:targets_items).and_return(targets) - @expected = subject.new - end - end - end - - context 'when no :type = :vulnerable' do - let(:targets) { (expected[:vulnerable_targets_items] + expected[:targets_items_from_file]).uniq { |t| t.name } } - - it 'checks all targets, and merge the results with passive_detection' do - target = targets.sample - @expected = expected[:passive_detection] << target - - stub_targets_dont_exist(targets) - allow(target).to receive(:exists?).and_return(true) - - expect(subject).to receive(:targets_items).and_return(targets) - expect(subject).to receive(:passive_detection).and_return(expected[:passive_detection]) - end - - context 'when all targets dont exist' do - it 'returns the result from passive_detection' do - @expected = expected[:passive_detection] - - stub_targets_dont_exist(targets) - expect(subject).to receive(:targets_items).and_return(targets) - expect(subject).to receive(:passive_detection).and_return(@expected) - end - end - end - end - -end diff --git a/spec/shared_examples/wp_plugin_vulnerable.rb b/spec/shared_examples/wp_plugin_vulnerable.rb deleted file mode 100644 index 5569f603..00000000 --- a/spec/shared_examples/wp_plugin_vulnerable.rb +++ /dev/null @@ -1,26 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpPlugin::Vulnerable' do - - describe '#db_file' do - after { expect(subject.db_file).to eq @expected } - - context 'when :db_file is no set' do - it 'returns the default one' do - @expected = PLUGINS_FILE - end - end - - context 'when the :db_file is already set' do - it 'returns it' do - @expected = 'test.json' - subject.db_file = @expected - end - end - end - - describe '#identifier' do - its(:identifier) { should eq 'plugin-name' } - end - -end diff --git a/spec/shared_examples/wp_target/wp_config_backup.rb b/spec/shared_examples/wp_target/wp_config_backup.rb deleted file mode 100644 index 0e1502fb..00000000 --- a/spec/shared_examples/wp_target/wp_config_backup.rb +++ /dev/null @@ -1,61 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpTarget::WpConfigBackup' do - - let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_config_backup' } - let(:config_backup_files) { WpTarget::WpConfigBackup.config_backup_files } - - describe '#config_backup' do - - # set all @config_backup_files to point to a 404 - before :each do - config_backup_files.each do |backup_file| - file_url = wp_target.uri.merge(url_encode(backup_file)).to_s - - stub_request(:get, file_url).to_return(status: 404) - end - end - - it 'shoud return an empty array if no config backup is present' do - expect(wp_target.config_backup).to be_empty - end - - it 'returns an array with 1 backup file' do - expected = [] - - config_backup_files.sample(1).each do |backup_file| - file_url = wp_target.uri.merge(url_encode(backup_file)).to_s - expected << file_url - - stub_request_to_fixture(url: file_url, fixture: fixtures_dir + '/wp-config.php') - end - - wp_config_backup = wp_target.config_backup - expect(wp_config_backup).not_to be_empty - expect(wp_config_backup).to be === expected - end - - # Is there a way to factorise that one with the previous test ? - it 'returns an array with 2 backup file' do - expected = [] - - config_backup_files.sample(2).each do |backup_file| - file_url = wp_target.uri.merge(url_encode(backup_file)).to_s - expected << file_url - - stub_request_to_fixture(url: file_url, fixture: fixtures_dir + '/wp-config.php') - end - - wp_config_backup = wp_target.config_backup - expect(wp_config_backup).not_to be_empty - expect(wp_config_backup.sort).to be === expected.sort - end - end - - describe '#config_backup_files' do - it 'does not contain duplicates' do - expect(config_backup_files.flatten.uniq.length).to eq config_backup_files.length - end - end - -end diff --git a/spec/shared_examples/wp_target/wp_custom_directories.rb b/spec/shared_examples/wp_target/wp_custom_directories.rb deleted file mode 100644 index 514f271a..00000000 --- a/spec/shared_examples/wp_target/wp_custom_directories.rb +++ /dev/null @@ -1,143 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpTarget::WpCustomDirectories' do - - describe '#wp_content_dir' do - let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_content_dir' } - - after :each do - @wp_target = WpTarget.new(@target_url) if @target_url - - stub_request_to_fixture(url: @wp_target.url, fixture: @fixture) if @fixture - stub_request(:get, /.*\/wp-content\/?$/).to_return(:status => 200, :body => '') # default dir request - stub_request(:get, /.*\.html$/).to_return(:status => 200, :body => '') # 404 hash request - - expect(@wp_target.wp_content_dir).to be === @expected - end - - it 'returns the string set in the initialize method' do - @wp_target = WpTarget.new('http://example.localhost/', options.merge(wp_content_dir: 'hello-world')) - @expected = 'hello-world' - end - - it "returns 'wp-content'" do - @target_url = 'http://lamp/wordpress-3.4.1' - @fixture = fixtures_dir + '/wordpress-3.4.1.htm' - @expected = 'wp-content' - end - - it "returns 'wp-content' if url has trailing slash" do - @target_url = 'http://lamp/wordpress-3.4.1/' - @fixture = fixtures_dir + '/wordpress-3.4.1.htm' - @expected = 'wp-content' - end - - it "should find the default 'wp-content' dir even if the target_url is not the same (ie : the user supply an IP address and the url used in the code is a domain)" do - @target_url = 'http://192.168.1.103/wordpress-3.4.1/' - @fixture = fixtures_dir + '/wordpress-3.4.1.htm' - @expected = 'wp-content' - end - - it "returns 'custom-content'" do - @target_url = 'http://lamp/wordpress-3.4.1-custom' - @fixture = fixtures_dir + '/wordpress-3.4.1-custom.htm' - @expected = 'custom-content' - end - - it "returns 'custom content spaces'" do - @target_url = 'http://lamp/wordpress-3.4.1-custom' - @fixture = fixtures_dir + '/wordpress-3.4.1-custom-with-spaces.htm' - @expected = 'custom content spaces' - end - - it "returns 'custom-dir/subdir/content'" do - @target_url = 'http://lamp/wordpress-3.4.1-custom' - @fixture = fixtures_dir + '/wordpress-3.4.1-custom-subdirectories.htm' - @expected = 'custom-dir/subdir/content' - end - - it 'should also check in src attributes' do - @target_url = 'http://lamp/wordpress-3.4.1' - @fixture = fixtures_dir + '/wordpress-3.4.1-in-src.htm' - @expected = 'wp-content' - end - - it 'should find the location even if the src or href goes in the plugins dir' do - @target_url = 'http://wordpress-3.4.1-in-plugins.htm' - @fixture = fixtures_dir + '/wordpress-3.4.1-in-plugins.htm' - @expected = 'wp-content' - end - - it 'should not detect facebook.com as a custom wp-content directory' do - @target_url = 'http://lamp.localhost/' - @fixture = fixtures_dir + '/facebook-detection.htm' - @expected = nil - end - end - - describe '#default_wp_content_dir_exists?' do - after :each do - @wp_target = WpTarget.new('http://lamp.localhost/') - stub_request(:get, @wp_target.url).to_return(:status => 200, :body => 'homepage') # homepage request - - expect(@wp_target.default_wp_content_dir_exists?).to be === @expected - end - - it 'returns false if wp-content returns an invalid response code' do - stub_request(:get, /.*\/wp-content\/?$/).to_return(:status => 404, :body => '') # default dir request - stub_request(:get, /.*\.html$/).to_return(:status => 404, :body => '') # 404 hash request - @expected = false - end - - it 'returns false if wp-content and homepage have same bodies' do - stub_request(:get, /.*\/wp-content\/?$/).to_return(:status => 200, :body => 'homepage') # default dir request - stub_request(:get, /.*\.html$/).to_return(:status => 404, :body => '404!') # 404 hash request - @expected = false - end - - it 'returns false if wp-content and 404 page have same bodies' do - stub_request(:get, /.*\/wp-content\/?$/).to_return(:status => 200, :body => '404!') # default dir request - stub_request(:get, /.*\.html$/).to_return(:status => 404, :body => '404!') # 404 hash request - @expected = false - end - - it 'returns true if wp-content, 404 page and hoempage return different bodies' do - stub_request(:get, /.*\/wp-content\/?$/).to_return(:status => 200, :body => '') # default dir request - stub_request(:get, /.*\.html$/).to_return(:status => 200, :body => '404!') # 404 hash request - @expected = true - end - end - - describe '#wp_plugins_dir' do - after :each do - expect(@wp_target.wp_plugins_dir).to be === @expected - end - - it 'returns the string set in the initialize method' do - @wp_target = WpTarget.new('http://example.localhost/', options.merge(wp_content_dir: 'asdf', wp_plugins_dir: 'custom-plugins')) - @expected = 'custom-plugins' - end - - it "returns 'custom/plugins'" do - @wp_target = WpTarget.new('http://example.localhost/', options.merge(wp_content_dir: 'custom', wp_plugins_dir: nil)) - @expected = 'custom/plugins' - end - end - - describe '#wp_plugins_dir_exists?' do - let(:wp_target) { WpTarget.new('http://example.localhost/', custom_options) } - let(:custom_options) { options.merge(wp_content_dir: 'asdf', wp_plugins_dir: 'custom-plugins') } - let(:url) { wp_target.uri.merge(wp_target.wp_plugins_dir).to_s } - - it 'returns true' do - stub_request(:get, url).to_return(status: 200) - expect(wp_target.wp_plugins_dir_exists?).to eq true - end - - it 'returns false' do - stub_request(:get, url).to_return(status: 404) - expect(wp_target.wp_plugins_dir_exists?).to eq false - end - end - -end diff --git a/spec/shared_examples/wp_target/wp_full_path_disclosure.rb b/spec/shared_examples/wp_target/wp_full_path_disclosure.rb deleted file mode 100644 index 39a63bf6..00000000 --- a/spec/shared_examples/wp_target/wp_full_path_disclosure.rb +++ /dev/null @@ -1,37 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpTarget::WpFullPathDisclosure' do - - let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_full_path_disclosure' } - - describe '#full_path_disclosure_url' do - it 'returns http://example.localhost/wp-includes/rss-functions.php' do - expect(wp_target.full_path_disclosure_url).to be === 'http://example.localhost/wp-includes/rss-functions.php' - end - end - - describe '#has_full_path_disclosure?' do - after do - stub_request(:get, wp_target.full_path_disclosure_url). - to_return(@stub) - - expect(wp_target.has_full_path_disclosure?).to be === @expected - end - - it 'returns false on a 404' do - @stub = { status: 404 } - @expected = false - end - - it 'returns false if no fpd found (blank page for example)' do - @stub = { status: 200, body: '' } - @expected = false - end - - it 'returns true' do - @stub = { status: 200, body: File.new(fixtures_dir + '/rss-functions-disclosure.php') } - @expected = true - end - end - -end diff --git a/spec/shared_examples/wp_target/wp_login_protection.rb b/spec/shared_examples/wp_target/wp_login_protection.rb deleted file mode 100644 index 5a959683..00000000 --- a/spec/shared_examples/wp_target/wp_login_protection.rb +++ /dev/null @@ -1,91 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpTarget::WpLoginProtection' do - - let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_login_protection' } - - before { allow(wp_target).to receive(:wp_plugins_dir).and_return('wp-content/plugins') } - - # It will test all protected methods has_.*_protection with each fixtures to be sure that - # there is not false positive : for example the login-lock must not be detected as login-lockdown - describe '#has_.*_protection?' do - - pattern = WpTarget::WpLoginProtection::LOGIN_PROTECTION_METHOD_PATTERN - fixtures = %w( - wp-login-clean.php wp-login-login_lockdown.php wp-login-login_lock.php - wp-login-better_wp_security.php wp-login-simple_login_lockdown.php - wp-login-login_security_solution.php wp-login-limit_login_attempts.php - wp-login-bluetrait_event_viewer.php wp-login-security_protection.php - ) - - # For plugins which are detected from the existence of their directory into wp-content/plugins/ (or one of their file) - # and not from a regex into the login page - special_plugins = %w(better_wp_security simple_login_lockdown login_security_solution limit_login_attempts bluetrait_event_viewer) - - after :each do - stub_request_to_fixture(url: login_url, fixture: @fixture) - - # Stub all special plugins urls to a 404 except if it's the one we want - special_plugins.each do |special_plugin| - special_plugin_call_detection_symbol = :"has_#{special_plugin}_protection?" - special_plugin_call_url_symbol = :"#{special_plugin}_url" - - status_code = (@symbol_to_call === special_plugin_call_detection_symbol and @expected === true) ? 200 : 404 - stub_request(:get, wp_target.send(special_plugin_call_url_symbol).to_s).to_return(status: status_code) - end - - expect(wp_target.send(@symbol_to_call)).to eql @expected - end - - protected_instance_methods.grep(pattern).each do |symbol_to_call| - plugin_name_from_symbol = symbol_to_call[pattern, 1].gsub('_', '-') - - fixtures.each do |fixture| - plugin_name_from_fixture = fixture[/wp-login-(.*)\.php/i, 1].gsub('_', '-') - expected = plugin_name_from_fixture === plugin_name_from_symbol ? true : false - - it "#{symbol_to_call} with #{fixture} returns #{expected}" do - @plugin_name = plugin_name_from_fixture - @fixture = File.join(fixtures_dir, fixture) - @symbol_to_call = symbol_to_call - @expected = expected - end - end - end - end - - describe '#login_protection_plugin' do - after :each do - stub_request(:get, /.*/).to_return(status: 404) - stub_request_to_fixture(url: login_url, fixture: @fixture) - - expect(wp_target.login_protection_plugin).to eq @plugin_expected - expect(wp_target.has_login_protection?).to eql @protection_expected - end - - it 'returns nil if no protection is present' do - @fixture = File.join(fixtures_dir, 'wp-login-clean.php') - @plugin_expected = nil - @protection_expected = false - end - - it 'returns a login-lockdown WpPlugin object' do - @fixture = File.join(fixtures_dir, 'wp-login-login_lockdown.php') - @plugin_expected = WpPlugin.new(wp_target.uri, name: 'login-lockdown') - @protection_expected = true - end - - it 'returns a login-lock WpPlugin object' do - @fixture = File.join(fixtures_dir, 'wp-login-login_lock.php') - @plugin_expected = WpPlugin.new(wp_target.uri, name: 'login-lock') - @protection_expected = true - end - - it 'returns a security-protection WpPlugin object' do - @fixture = File.join(fixtures_dir, 'wp-login-security_protection.php') - @plugin_expected = WpPlugin.new(wp_target.uri, name: 'security-protection') - @protection_expected = true - end - end - -end diff --git a/spec/shared_examples/wp_target/wp_readme.rb b/spec/shared_examples/wp_target/wp_readme.rb deleted file mode 100644 index 7d9f6241..00000000 --- a/spec/shared_examples/wp_target/wp_readme.rb +++ /dev/null @@ -1,36 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpTarget::WpReadme' do - - let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_readme' } - - describe '#readme_url' do - it 'returns http://example.localhost/readme.html' do - expect(wp_target.readme_url).to be === "#{wp_target.uri}readme.html" - end - end - - describe '#has_readme?' do - after do - stub_request(:get, wp_target.readme_url).to_return(@stub) - - expect(wp_target.has_readme?).to be === @expected - end - - it 'returns false on a 404' do - @stub = { status: 404 } - @expected = false - end - - it 'returns true if it exists' do - @stub = { status: 200, body: File.new(fixtures_dir + '/readme-3.2.1.html') } - @expected = true - end - - it 'returns true even if the readme.html is not in english' do - @stub = { status: 200, body: File.new(fixtures_dir + '/readme-3.3.2-fr.html') } - @expected = true - end - end - -end diff --git a/spec/shared_examples/wp_target/wp_registrable.rb b/spec/shared_examples/wp_target/wp_registrable.rb deleted file mode 100644 index 6938b4d1..00000000 --- a/spec/shared_examples/wp_target/wp_registrable.rb +++ /dev/null @@ -1,96 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpTarget::WpRegistrable' do - - let(:signup_url) { wp_target.uri.merge('wp-signup.php').to_s } - - describe '#registration_url' do - after { expect(wp_target.registration_url).to be === @expected } - - context 'when multisite' do - it 'returns the signup url' do - allow(wp_target).to receive(:multisite?).and_return(true) - - @expected = signup_url - end - end - - context 'when not multisite' do - it 'returns the login url with ?action=register' do - allow(wp_target).to receive(:multisite?).and_return(false) - - @expected = login_url + '?action=register' - end - end - end - - describe '#registration_enabled?' do - after do - allow(wp_target).to receive(:multisite?).and_return(multisite) - stub_request(:get, wp_target.registration_url).to_return(@stub) - - expect(wp_target.registration_enabled?).to be === @expected - end - - context 'when multisite' do - let(:multisite) { true } - it 'returns false' do - @stub = { status: 302, headers: { 'Location' => 'wp-login.php?registration=disabled' } } - @expected = false - end - - it 'returns true' do - @stub = { status: 200, body: '
    '} - @expected = true - end - end - - context 'when not multisite' do - let(:multisite) { false } - - it 'returns false' do - @stub = { status: 302, headers: { 'Location' => 'wp-login.php?registration=disabled' } } - @expected = false - end - - it 'returns true' do - @stub = { status: 200, body: ' 'wp-login.php?action=register' } } - @expected = false - end - - it 'returns true' do - @stub = { status: 302, headers: { 'Location' => 'http://example.localhost/wp-signup.php' } } - @expected = true - end - - it 'returns true' do - @stub = { status: 200 } - @expected = true - end - - it 'returns false' do - @stub = { status: 500 } - @expected = false - end - end - -end diff --git a/spec/shared_examples/wp_theme_versionable.rb b/spec/shared_examples/wp_theme_versionable.rb deleted file mode 100644 index c3148d88..00000000 --- a/spec/shared_examples/wp_theme_versionable.rb +++ /dev/null @@ -1,48 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpTheme::Versionable' do - let(:fixtures_dir) { MODELS_FIXTURES + '/wp_theme/versionable/' } - - describe '#version' do - after do - if @file - body = File.new(fixtures_dir + @file) - stub_request(:get, subject.style_url).to_return(status: 200, body: body) - end - - expect(subject.version).to eq @expected - end - - context 'the version is already set' do - it 'returns it' do - subject.version = '2.1' - @expected = '2.1' - end - end - - context 'when the version is not found' do - it 'returns nil' do - @file = 'twentyeleven-unknow.css' - @expected = nil - end - end - - context 'when the stylesheet is inline' do - it 'returns the correct version' do - @file = 'bueno-1.5.1.css' - @expected = '1.5.1' - end - end - - it 'returns the correct version' do - @file = 'twentyeleven-1.3.css' - @expected = '1.3' - end - - it 'returns the correct version' do - @file = 'firefart.net.css' - @expected = '1.0.0' - end - end - -end diff --git a/spec/shared_examples/wp_theme_vulnerable.rb b/spec/shared_examples/wp_theme_vulnerable.rb deleted file mode 100644 index 032a8408..00000000 --- a/spec/shared_examples/wp_theme_vulnerable.rb +++ /dev/null @@ -1,26 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpTheme::Vulnerable' do - - describe '#db_file' do - after { expect(subject.db_file).to eq @expected } - - context 'when :db_file is not set' do - it 'returns the default one' do - @expected = THEMES_FILE - end - end - - context 'when the :db_file is already set' do - it 'returns it' do - @expected = 'test.json' - subject.db_file = @expected - end - end - end - - describe '#identifier' do - its(:identifier) { should eq 'theme-name' } - end - -end diff --git a/spec/shared_examples/wp_timthumb_existable.rb b/spec/shared_examples/wp_timthumb_existable.rb deleted file mode 100644 index d905dfad..00000000 --- a/spec/shared_examples/wp_timthumb_existable.rb +++ /dev/null @@ -1,37 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpTimthumb::Existable' do - - describe 'exists_from_response?' do - after do - response = Typhoeus::Response.new(@resp_opt) - expect(subject.send(:exists_from_response?, response)).to eq @expected - end - - context 'when the status is not a 400' do - it 'returns false' do - @resp_opt = { code: 200 } - @expected = false - end - end - - context 'when the status is a 400' do - let(:opt) { { code: 400 } } - - context 'when the body contains "no image specified"' do - it 'returns true' do - @resp_opt = opt.merge(body: 'The following error(s) occured:
    No image specified') - @expected = true - end - end - - context 'otherwise' do - it 'returns false' do - @resp_opt = opt.merge(body: 'im a fake one, hehe') - @expected = false - end - end - end - end - -end diff --git a/spec/shared_examples/wp_timthumb_versionable.rb b/spec/shared_examples/wp_timthumb_versionable.rb deleted file mode 100644 index fa9e8660..00000000 --- a/spec/shared_examples/wp_timthumb_versionable.rb +++ /dev/null @@ -1,52 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpTimthumb::Versionable' do - - describe '#version' do - after do - stub_request(:get, subject.url).to_return(status: 200, body: @body) - - expect(subject.version).to be === @expected - end - - context 'when a version is already set' do - it 'returns it' do - subject.version = '2.3.1' - @expected = '2.3.1' - end - end - - context 'when the body match' do - it 'returns the version' do - @body = 'Query String :
    TimThumb version : 2.8.10' - @expected = '2.8.10' - end - end - - context 'otherwise' do - it 'returns nil' do - @body = 'not in here' - @expected = nil - end - end - end - - describe '#to_s' do - after { expect(subject.to_s).to eq @expected } - - context 'when there is a version' do - it 'returns it with the url' do - subject.version = '1.3' - @expected = uri.merge(options[:path]).to_s + ' v1.3' - end - end - - context 'when there is not a version' do - it 'returns only the url' do - allow(subject).to receive(:version).and_return(nil) - @expected = uri.merge(options[:path]).to_s - end - end - end - -end diff --git a/spec/shared_examples/wp_user/brute_forcable.rb b/spec/shared_examples/wp_user/brute_forcable.rb deleted file mode 100644 index 04a7fd4b..00000000 --- a/spec/shared_examples/wp_user/brute_forcable.rb +++ /dev/null @@ -1,139 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpUser::BruteForcable' do - let(:fixtures_dir) { MODELS_FIXTURES + '/wp_user/brute_forcable' } - let(:wordlist_iso) { fixtures_dir + '/wordlist-iso-8859-1.txt' } - let(:wordlist_utf8) { fixtures_dir + '/wordlist-utf-8.txt' } - let(:redirect_url) { 'http://www.example.com/asdf/' } - let(:mod) { WpUser::BruteForcable } - - before { Browser.instance.max_threads = 1 } - - describe '#valid_password?' do - let(:response) { Typhoeus::Response.new(resp_options) } - let(:resp_options) { {} } - - after do - expect(wp_user.valid_password?(response, 'password', redirect_url)).to eq @expected - end - - context 'when 302 and valid return_to parameter' do - let(:resp_options) { { code: 302, headers: { 'Location' => redirect_url } } } - - it 'returns true' do @expected = true end - end - - context 'when 302 and invalid return_to parameter' do - let(:resp_options) { { code: 302, headers: { 'Location' => nil } } } - - it 'returns false' do @expected = false end - end - - context 'when login_error' do - let(:resp_options) { { body: '
    ' } } - - it 'returns false' do @expected = false end - end - - context 'when timeout' do - let(:resp_options) { { return_code: :operation_timedout } } - - it 'returns false' do @expected = false end - end - - context 'when no response from server (status = 0)' do - let(:resp_options) { { code: 0 } } - - it 'returns false' do @expected = false end - end - - context 'when error 50x' do - let(:resp_options) { { code: 500 } } - - it 'returns false' do @expected = false end - end - - context 'when unknown response' do - let(:resp_options) { { code: 202 } } - - it 'returns false' do @expected = false end - end - end - - # TODO - describe '#login_request' do - - end - - describe '#brute_force' do - let(:login) { 'someuser' } - let(:login_url) { uri.merge('wp-login.php').to_s } - - after do - [wordlist_utf8, wordlist_iso].each do |wordlist| - wp_user.login = login - wp_user.brute_force(wordlist, {}, redirect_url) - expect(wp_user.password).to eq @expected - end - end - - context 'when no password is valid' do - before do - stub_request(:get, login_url).to_return(status: 200) - stub_request(:post, wp_user.login_url). - # with(body: { log: login }). # produces an error : undefined method `split' for {:log=>"someuser", :pwd=>"password1"}:Hash - # Fixed in WebMock 1.17.2, TODO: Modify the specs - to_return(body: 'login_error') - end - - it 'does not set @password' do - @expected = nil - end - end - - context 'when no redirect_url is given' do - let(:redirect_url) { nil } - - before do - stub_request(:get, login_url).to_return(status: 200) - stub_request(:post, wp_user.login_url).to_return(status: 302, headers: { 'Location' => 'wrong-location' }) - end - - it 'does not set the @password' do - @expected = nil - end - end - - context 'when a password is valid' do - # Due to the error with .with(body: { log: login }) above - # We can't use it to stub the request for a specific password - # So, the first one will be valid - # Fixed in WebMock 1.17.2, TODO: Modify the specs - - before do - stub_request(:get, login_url).to_return(status: 200) - stub_request(:post, wp_user.login_url).to_return(status: 302, headers: { 'Location' => redirect_url }) - end - - it 'sets the @password' do - @expected = 'password1' - end - end - - context 'when the login url is redirected to https' do - let(:https_login_url) { 'https://example.com/wp-login.php' } - - before do - stub_request(:any, uri.merge('wp-login.php').to_s).to_return(status: 302, headers: { 'Location' => https_login_url}) - stub_request(:get, https_login_url).to_return(status: 200) - stub_request(:post, https_login_url).with(body: hash_including({ log: 'someuser', pwd: 'root'})).to_return(status: 302, headers: { 'Location' => redirect_url }) - stub_request(:post, https_login_url).with(body: /pwd=(?!root)/).to_return(body: 'login_error') - end - - it 'does not raise any error' do - @expected = 'root' - end - end - end - -end diff --git a/spec/shared_examples/wp_user/existable.rb b/spec/shared_examples/wp_user/existable.rb deleted file mode 100644 index a09557b0..00000000 --- a/spec/shared_examples/wp_user/existable.rb +++ /dev/null @@ -1,202 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpUser::Existable' do - let(:mod) { WpUser::Existable } - let(:fixtures_dir) { File.join(MODELS_FIXTURES, 'wp_user', 'existable') } - - describe '::login_from_author_pattern' do - after do - expect(mod.login_from_author_pattern(@text)).to eq @expected - end - - context 'when no trailing slash' do - it 'returns the correct login' do - @text = '/aurhor/neo' - @expeced = 'neo' - end - end - - context 'when trailing slash' do - it 'returns the correct login' do - @text = '/author/admin/' - @expected = 'admin' - end - end - - context 'when pattern not found' do - it 'returns nil' do - @text = 'im not from this world' - @expected = nil - end - end - - context 'when no author given' do - it 'returns nil' do - @text = 'See Posts' - @expected = nil - end - end - end - - describe '::login_from_body' do - after { expect(mod.login_from_body(body)).to eq @expected } - - context 'when the author pattern is in the body' do - let(:body) { '/author/admin' } - - it 'returns it' do - allow(mod).to receive(:login_from_body).with(body).and_return('admin') - @expected = 'admin' - end - end - - context 'otherwise' do - let(:body) { '' } - - it 'gets the login from the body class' do - @expected = 'user2' - end - end - end - - describe '::display_name_from_body' do - after { expect(mod.display_name_from_body(@body)).to eq @expected } - - context 'when pattern not found' do - it 'returns nil' do - @body = 'im not there' - @expected = nil - end - end - - context 'when the title tag is empty' do - it 'returns nil' do - @body = '' - @expected = nil - end - end - - context 'when the body is an ASCII-8BIT' do - it 'return the correct display_name' do - @body = 'its me | wordpress'.encode('ASCII-8BIT') - @expected = 'its me' - end - end - - context 'when pattern is found' do - context 'when unencoded extra chars' do - it 'returns the display_name w/o extra chars' do - @body = 'admin display | Wordpress-3.5.1' - @expected = 'admin display' - end - end - - context 'when encoded extra chars' do - it 'returns the display_name w/o extra chars' do - @body = 'user user | Wordpress-3.5.1' - @expected = 'user user' - end - - context 'when custom extra chars' do - it 'detects them' do - @body = 'admin « Wiener' - @expected = 'admin' - end - end - end - - it 'decodes entities' do - @body = 'user & nickname | Wordpress-3.5.1' - @expected = 'user & nickname' - end - end - end - - describe '#load_from_response' do - after do - response = Typhoeus::Response.new(@resp_opt || resp_opt) - subject.send(:load_from_response, response) - - expect(subject.login).to eq @login - expect(subject.display_name).to eq @display_name - end - - context 'with a 301' do - let(:location) { 'http://lamp/wordpress-3.5.1/author/admin/' } - let(:resp_opt) { { code: 301, headers: { 'Location' => location } } } - - it 'loads the correct values' do - stub_request(:get, location).to_return(body: 'admin name | wp') - - @login = 'admin' - @display_name = 'admin name' - end - - context 'when the location is nil' do - let(:location) { nil } - - it 'returns nil' do - @login = nil - @display_name = nil - end - end - - context 'when the location is empty' do - let(:location) { '' } - - it 'returns nil' do - @login = nil - @display_name = nil - end - end - end - - context 'with a 200' do - let(:resp_opt) { { code: 200, body: File.read(File.join(fixtures_dir, 'admin.html')) } } - - it 'loads the correct values' do - @login = 'admin' - @display_name = 'admin d-name' - end - end - - context 'when chinese chars' do - let(:resp_opt) { { code: 200, body: File.read(File.join(fixtures_dir, 'chinese_chars.html')) } } - - it 'loads the correct values' do - @login = '一路疯下去' - @display_name = nil - end - end - - context 'otherwise' do - it 'does not do anything' do - @resp_opt = { code: 404 } - @login = nil - @display_name = nil - end - end - end - - describe '#exists_from_response?' do - after do - response = Typhoeus::Response.new(@resp_opt || resp_opt) - expect(subject.exists_from_response?(response)).to eq @expected - end - - context 'login not found' do - it 'returns false' do - @resp_opt = { code: 404 } - @expected = false - end - end - - context 'login found' do - it 'returns true' do - @resp_opt = { code: 200, body: File.new(fixtures_dir + '/admin.html').read } - @expected = true - end - end - end - -end diff --git a/spec/shared_examples/wp_users/brute_forcable.rb b/spec/shared_examples/wp_users/brute_forcable.rb deleted file mode 100644 index dccae8e0..00000000 --- a/spec/shared_examples/wp_users/brute_forcable.rb +++ /dev/null @@ -1,22 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpUsers::BruteForcable' do - - describe '#brute_force' do - let(:range) { (1..10) } - let(:wordlist) { 'somefile.txt'} - let(:brute_force_opt) { {} } - - it 'calls #brute_force on each wp_user' do - range.each do |id| - wp_user = WpUser.new(uri, id: id) - expect(wp_user).to receive(:brute_force).with(wordlist, brute_force_opt) - - wp_users << wp_user - end - - wp_users.brute_force(wordlist, brute_force_opt) - end - end - -end diff --git a/spec/shared_examples/wp_version_vulnerable.rb b/spec/shared_examples/wp_version_vulnerable.rb deleted file mode 100644 index a98b36ed..00000000 --- a/spec/shared_examples/wp_version_vulnerable.rb +++ /dev/null @@ -1,26 +0,0 @@ -# encoding: UTF-8 - -shared_examples 'WpVersion::Vulnerable' do - - describe '#db_file' do - after { expect(subject.db_file).to eq @expected } - - context 'when :db_file is no set' do - it 'returns the default one' do - @expected = WORDPRESSES_FILE - end - end - - context 'when the :db_file is already set' do - it 'returns it' do - @expected = 'test.json' - subject.db_file = @expected - end - end - end - - describe '#identifier' do - its(:identifier) { should eq '1.2' } - end - -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index 31dcd4fa..00000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,70 +0,0 @@ -# encoding: UTF-8 - -require 'rspec/its' -require 'webmock/rspec' -# Code Coverage (only works with ruby >= 1.9) -require 'simplecov' if RUBY_VERSION >= '1.9' - -RSpec::Expectations.configuration.warn_about_potential_false_positives = false - -require File.expand_path(File.join(__dir__, '..', 'lib', 'common', 'common_helper')) - -SPEC_DIR = ROOT_DIR + '/spec' -SPEC_LIB_DIR = SPEC_DIR + '/lib' -SPEC_CACHE_DIR = SPEC_DIR + '/cache' # FIXME remove it -SPEC_FIXTURES_DIR = SPEC_DIR + '/samples' -SHARED_EXAMPLES_DIR = SPEC_DIR + '/shared_examples' -SPEC_FIXTURES_CONF_DIR = SPEC_FIXTURES_DIR + '/conf' # FIXME Remove it -SPEC_FIXTURES_WP_VERSIONS_DIR = SPEC_FIXTURES_DIR + '/wp_versions' - -redefine_constant(:CACHE_DIR, SPEC_DIR + '/cache') -redefine_constant(:CONF_DIR, SPEC_FIXTURES_DIR + '/conf') - -MODELS_FIXTURES = SPEC_FIXTURES_DIR + '/common/models' -COLLECTIONS_FIXTURES = SPEC_FIXTURES_DIR + '/common/collections' - -# Load all the shared examples -require_files_from_directory(SHARED_EXAMPLES_DIR, '**/*.rb') - -def count_files_in_dir(absolute_dir_path, files_pattern = '*') - Dir.glob(File.join(absolute_dir_path, files_pattern)).count -end - -# a trick to be able to test command line arguments -# argv must be an array or a string -def set_argv(argv) - if argv.is_a?(Array) - Object.send(:remove_const, :ARGV) - Object.const_set(:ARGV, argv) - elsif argv.is_a?(String) - set_argv(argv.split(' ')) - end -end - -# arguments : -# :url - mandatory -# :fixture - mandatory -# :method - optional (:get, :post, :any), default :get -# :status - optional, default 200 -def stub_request_to_fixture(arguments = {}) - arguments[:method] ||= :get - arguments[:status] ||= 200 - raise 'No arguments[:url] supplied' if arguments[:url].nil? - raise 'No arguments[:fixture] supplied' if arguments[:fixture].nil? - - stub_request(arguments[:method], arguments[:url].to_s). - to_return( - status: arguments[:status], - body: File.new(arguments[:fixture]) - ) -end - -# The object must be given as we will mock the Kernel#` or -# Kernel#system (Kernel is a module) -# -# system_method : -# :` for `` or %x -# :system for system() -def stub_system_command(object, command, return_value, system_method = :`) - expect(object).to receive(system_method).with(command).and_return(return_value) -end diff --git a/spec/wpscan_spec.rb b/spec/wpscan_spec.rb deleted file mode 100644 index 845fa5a0..00000000 --- a/spec/wpscan_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -# encoding: UTF-8 - -require 'spec_helper' - -describe 'wpscan main checks' do - - it 'should check for errors on running the mainscript' do - a = %x[#{RbConfig.ruby} #{ROOT_DIR}/wpscan.rb] - expect(a).to match /No argument supplied/ - end - - it 'should check for valid syntax' do - result = '' - Dir.glob('**/*.rb') do |file| - res = %x{#{RbConfig.ruby} -c #{ROOT_DIR}/#{file} 2>&1}.split("\n") - ok = res.select {|msg| msg =~ /Syntax OK/} - result << ("####################\nSyntax error in #{file}:\n#{res.join("\n").strip}\n") if ok.size != 1 - end - fail(result) unless result.empty? - end -end diff --git a/stop_user_enumeration_bypass.rb b/stop_user_enumeration_bypass.rb deleted file mode 100755 index 2d247ae0..00000000 --- a/stop_user_enumeration_bypass.rb +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env ruby -# encoding: UTF-8 -# -# -# Script based on http://seclists.org/fulldisclosure/2014/Feb/3 - -require File.join(__dir__, 'lib', 'wpscan', 'wpscan_helper') - -@opts = { - ids: 1..10, - verbose: false, - user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0' -} - -parser = OptionParser.new('Usage: ./stop_user_enumeration_bypass.rb [options]', 35) do |opts| - opts.on('--proxy PROXY', 'Proxy to use') do |proxy| - @opts[:proxy] = proxy - end - - opts.on('--auth Username:Password', 'Credentials to use if Basic/NTLM auth') do |creds| - @opts[:creds] = creds - end - - opts.on('--ids START-END', 'The ids to check, default is 1-10') do |ids| - @opts[:ids] = Range.new(*ids.split('-').map(&:to_i)) - end - - opts.on('--user-agent UA', 'The user-agent to use') do |ua| - @opts[:user_agent] = ua - end - - opts.on('--verbose', '-v', 'Verbose Mode') do - @opts[:verbose] = true - end -end - -begin - parser.parse! - - fail "#{critical('The target URL must be supplied')}\n\n#{parser}" unless ARGV[0] - - uri = URI.parse(add_trailing_slash(add_http_protocol(ARGV[0]))).to_s - - request_params = { - proxy: @opts[:proxy], - userpwd: @opts[:creds], - headers: { 'User-Agent' => @opts[:user_agent] }, - followlocation: true, - ssl_verifypeer: false, - ssl_verifyhost: 2 - } - - detected_users = WpUsers.new - - @opts[:ids].each do |user_id| - user = WpUser.new(uri, id: user_id) - - if user.exists_from_response?( - Typhoeus.post(uri, request_params.merge(body: { author: user_id })) - ) - detected_users << user - end - end - - puts 'Usernames found:' - detected_users.output -rescue => e - puts e.message - - if @opts[:verbose] - puts critical('Trace:') - puts critical(e.backtrace.join("\n")) - end - exit(1) -end diff --git a/wpscan.rb b/wpscan.rb deleted file mode 100755 index 76113f12..00000000 --- a/wpscan.rb +++ /dev/null @@ -1,627 +0,0 @@ -#!/usr/bin/env ruby -# encoding: UTF-8 - -$: << '.' - -$exit_code = 0 - -require File.join(__dir__, 'lib', 'wpscan', 'wpscan_helper') - -def main - begin - wpscan_options = WpscanOptions.load_from_arguments - date = last_update - - $log = wpscan_options.log - - # some sanity checks - if $log - if $log.empty? - $log = DEFAULT_LOG_FILE - end - - # translate to full path if no starting / detected - if $log !~ /^#{File::SEPARATOR}/ - $log = File.join(ROOT_DIR, $log) - end - - # check if file exists and has a size greater zero - if File.exist?($log) && File.size?($log) - puts notice("The supplied log file #{$log} already exists. If you continue the new output will be appended.") - print '[?] Do you want to continue? [Y]es [N]o, default: [N] >' - if Readline.readline !~ /^y/i - # unset logging so puts will try to log to the file - $log = nil - puts notice('Scan aborted') - exit(1) - end - end - - # check if we can write the file - begin - File.open($log, 'a') - rescue SystemCallError => e - # unset logging so puts will try to log to the file - temp = $log - $log = nil - puts critical("Error with logfile #{temp}:") - puts critical(e) - exit(1) - end - end - - banner() unless wpscan_options.no_banner # called after $log set - - unless wpscan_options.has_options? - # first parameter only url? - if ARGV.length == 1 - puts - puts notice("Please use '-u #{ARGV[0]}' next time") - wpscan_options.url = ARGV[0] - else - usage() - raise('No argument supplied') - end - end - - # Define a global variable - $COLORSWITCH = wpscan_options.no_color - - if wpscan_options.help - help() - usage() - exit(0) - end - - if wpscan_options.version - puts "Current version: #{WPSCAN_VERSION}" - puts "Last database update: #{date.strftime('%Y-%m-%d')}" unless date.nil? - exit(0) - end - - # Initialize the browser to allow the db update - # to be done over a proxy if set - Browser.instance( - wpscan_options.to_h.merge(max_threads: wpscan_options.threads) - ) - - # Check if database needs upgrade (if its older than 5 days) and we are not running in --batch mode - # Also no need to check if the user supplied the --update switch - if update_required? and not wpscan_options.batch and not wpscan_options.update - # Banner - puts - puts notice('It seems like you have not updated the database for some time') - puts notice("Last database update: #{date.strftime('%Y-%m-%d')}") unless date.nil? - - # User prompt - print '[?] Do you want to update now? [Y]es [N]o [A]bort update, default: [N] > ' - if (input = Readline.readline) =~ /^a/i - puts 'Update aborted' - elsif input =~ /^y/i - wpscan_options.update = true - end - - # Is there a database to go on with? - if missing_db_files? and not wpscan_options.update - # Check for data.zip - if has_db_zip? - puts notice('Extracting the Database ...') - # Extract data.zip - extract_db_zip - puts notice('Extraction completed') - # Missing, so can't go on! - else - puts critical('You can not run a scan without any databases') - exit(1) - end - end - end - - # Should we update? - if wpscan_options.update - puts notice('Updating the Database ...') - DbUpdater.new(DATA_DIR).update(wpscan_options.verbose) - puts notice('Update completed') - - # Exit program if only option --update is used - exit(0) unless wpscan_options.url - end - - unless wpscan_options.url - raise 'The URL is mandatory, please supply it with --url or -u' - end - - wp_target = WpTarget.new(wpscan_options.url, wpscan_options.to_h) - - if wp_target.wordpress_hosted? - raise 'We do not support scanning *.wordpress.com hosted blogs' - end - - if wp_target.ssl_error? - raise "The target site returned an SSL/TLS error. You can try again using --disable-tls-checks\nError: #{wp_target.get_root_path_return_code}\nSee here for a detailed explanation of the error: http://www.rubydoc.info/github/typhoeus/ethon/Ethon/Easy:return_code" - end - - # Remote website up? - unless wp_target.online? - if wpscan_options.user_agent - puts info("User-Agent: #{wpscan_options.user_agent}") - raise "The WordPress URL supplied '#{wp_target.uri}' seems to be down. Maybe the site is blocking the user-agent?" - else - raise "The WordPress URL supplied '#{wp_target.uri}' seems to be down. Maybe the site is blocking the wpscan user-agent, so you can try --random-agent" - end - - end - - if wpscan_options.proxy - proxy_response = Browser.get(wp_target.url) - - unless WpTarget::valid_response_codes.include?(proxy_response.code) - raise "Proxy Error :\r\nResponse Code: #{proxy_response.code}\r\nResponse Headers: #{proxy_response.headers}" - end - end - - # Remote website has a redirection? - if (redirection = wp_target.redirection) - if redirection =~ /\/wp-admin\/install\.php$/ - puts critical('The Website is not fully configured and currently in install mode. Call it to create a new admin user.') - else - if wpscan_options.follow_redirection - puts "Following redirection #{redirection}" - else - puts notice("The remote host tried to redirect to: #{redirection}") - print '[?] Do you want follow the redirection ? [Y]es [N]o [A]bort, default: [N] >' - end - if wpscan_options.follow_redirection || !wpscan_options.batch - if wpscan_options.follow_redirection || (input = Readline.readline) =~ /^y/i - wpscan_options.url = redirection - wp_target = WpTarget.new(redirection, wpscan_options.to_h) - else - if input =~ /^a/i - puts 'Scan aborted' - exit(1) - end - end - end - end - end - - if wp_target.has_basic_auth? && wpscan_options.basic_auth.nil? - raise 'Basic authentication is required, please provide it with --basic-auth ' - end - - # test for valid credentials - unless wpscan_options.basic_auth.nil? - res = Browser.get_and_follow_location(wp_target.url) - raise 'Invalid credentials supplied' if res && res.code == 401 - end - - # Remote website is wordpress? - unless wpscan_options.force - unless wp_target.wordpress? - raise 'The remote website is up, but does not seem to be running WordPress. If you are sure, use --force' - end - end - - unless wp_target.wp_content_dir - raise 'The wp_content_dir has not been found, please supply it with --wp-content-dir' - end - - unless wp_target.wp_plugins_dir_exists? - puts "The plugins directory '#{wp_target.wp_plugins_dir}' does not exist." - puts 'You can specify one per command line option (don\'t forget to include the wp-content directory if needed)' - puts '[?] Continue? [Y]es [N]o, default: [N]' - if wpscan_options.batch || Readline.readline !~ /^y/i - exit(1) - end - end - - # Output runtime data - start_time = Time.now - start_memory = get_memory_usage unless windows? - puts info("URL: #{wp_target.url}") - puts info("Started: #{start_time.asctime}") - puts info("User-Agent: #{wpscan_options.user_agent}") if wpscan_options.verbose and wpscan_options.user_agent - puts - - wp_target.interesting_headers.each do |header| - output = info('Interesting header: ') - - if header[1].class == Array - header[1].each do |value| - puts output + "#{header[0]}: #{value}" - end - else - puts output + "#{header[0]}: #{header[1]}" - end - end - - if wp_target.has_robots? - code = get_http_status(wp_target.robots_url) - puts info("robots.txt available under: #{wp_target.robots_url} [HTTP #{code}]") - - wp_target.parse_robots_txt.each do |dir| - code = get_http_status(dir) - puts info("Interesting entry from robots.txt: #{dir} [HTTP #{code}]") - end - end - - if wp_target.has_sitemap? - code = get_http_status(wp_target.sitemap_url) - puts info("Sitemap found: #{wp_target.sitemap_url} [HTTP #{code}]") - - wp_target.parse_sitemap.each do |dir| - code = get_http_status(dir) - puts info("Sitemap entry: #{dir} [HTTP #{code}]") - end - end - - code = get_http_status(wp_target.humans_url) - if code == 200 - puts info("humans.txt available under: #{wp_target.humans_url} [HTTP #{code}]") - - parse_txt(wp_target.humans_url).each do |dir| - puts info("Entry from humans.txt: #{dir}") - end - end - - code = get_http_status(wp_target.security_url) - if code == 200 - puts info("security.txt available under: #{wp_target.security_url} [HTTP #{code}]") - - parse_txt(wp_target.security_url).each do |dir| - puts info("Entry from security.txt: #{dir}") - end - end - - unless wp_target.sql_file_export.empty? - wp_target.sql_file_export.each do |file| - puts critical("SQL export file found: #{file}") - end - end - - if wp_target.has_debug_log? - puts critical("Debug log file found: #{wp_target.debug_log_url}") - end - - wp_target.config_backup.each do |file_url| - puts critical("A wp-config.php backup file has been found in: #{file_url}") - end - - if wp_target.search_replace_db_2_exists? - puts critical("searchreplacedb2.php has been found in: #{wp_target.search_replace_db_2_url}") - end - - if wp_target.emergency_exists? - puts critical("emergency.php has been found in: #{wp_target.emergency_url}") - end - - if wp_target.multisite? - puts info('This site seems to be a multisite (http://codex.wordpress.org/Glossary#Multisite)') - end - - if wp_target.has_must_use_plugins? - puts info("This site has 'Must Use Plugins' (http://codex.wordpress.org/Must_Use_Plugins)") - end - - if wp_target.has_xml_rpc? - code = get_http_status(wp_target.xml_rpc_url) - puts info("XML-RPC Interface available under: #{wp_target.xml_rpc_url} [HTTP #{code}]") - end - - # Test to see if MAIN API URL gives anything back - if wp_target.has_api?(wp_target.json_url) - code = get_http_status(wp_target.json_url) - puts info("API exposed: #{wp_target.json_url} [HTTP #{code}]") - - # Test to see if USER API URL gives anything back - if wp_target.has_api?(wp_target.json_users_url) - # Print users from JSON - wp_target.json_get_users(wp_target.json_users_url) - end - end - - # Get RSS - rss = wp_target.rss_url - if rss - code = get_http_status(rss) - puts info("Found an RSS Feed: #{rss} [HTTP #{code}]") - - # Print users from RSS feed - wp_target.rss_authors(rss) - end - - if wp_target.has_full_path_disclosure? - puts warning("Full Path Disclosure (FPD) in '#{wp_target.full_path_disclosure_url}': #{wp_target.full_path_disclosure_data}") - end - - if wp_target.upload_directory_listing_enabled? - puts warning("Upload directory has directory listing enabled: #{wp_target.upload_dir_url}") - end - - if wp_target.include_directory_listing_enabled? - puts warning("Includes directory has directory listing enabled: #{wp_target.includes_dir_url}") - end - - enum_options = { - show_progression: true, - exclude_content: wpscan_options.exclude_content_based - } - - puts - puts info('Enumerating WordPress version ...') - if (wp_version = wp_target.version(WP_VERSIONS_FILE)) - if wp_target.has_readme? && VersionCompare::lesser?(wp_version.identifier, '4.7') - puts warning("The WordPress '#{wp_target.readme_url}' file exists exposing a version number") - end - - wp_version.output(wpscan_options.verbose) - else - puts - puts notice('WordPress version can not be detected') - end - - - if wp_theme = wp_target.theme - puts - # Theme version is handled in #to_s - puts info("WordPress theme in use: #{wp_theme}") - wp_theme.output(wpscan_options.verbose) - - # Check for parent Themes - parent_theme_count = 0 - while wp_theme.is_child_theme? && parent_theme_count <= wp_theme.parent_theme_limit - parent_theme_count += 1 - - parent = wp_theme.get_parent_theme - puts - puts info("Detected parent theme: #{parent}") - parent.output(wpscan_options.verbose) - wp_theme = parent - end - - end - - if wpscan_options.enumerate_plugins == nil and wpscan_options.enumerate_only_vulnerable_plugins == nil - puts - puts info('Enumerating plugins from passive detection ...') - - wp_plugins = WpPlugins.passive_detection(wp_target) - if !wp_plugins.empty? - grammar = grammar_s(wp_plugins.size) - puts " | #{wp_plugins.size} plugin#{grammar} found:" - wp_plugins.output(wpscan_options.verbose) - else - puts info('No plugins found passively') - end - end - - # Enumerate the installed plugins - if wpscan_options.enumerate_plugins or wpscan_options.enumerate_only_vulnerable_plugins or wpscan_options.enumerate_all_plugins - puts - if wpscan_options.enumerate_only_vulnerable_plugins - puts info('Enumerating installed plugins (only ones with known vulnerabilities) ...') - plugin_enumeration_type = :vulnerable - end - - if wpscan_options.enumerate_plugins - puts info('Enumerating installed plugins (only ones marked as popular) ...') - plugin_enumeration_type = :popular - end - - if wpscan_options.enumerate_all_plugins - puts info('Enumerating all plugins (may take a while and use a lot of system resources) ...') - plugin_enumeration_type = :all - end - puts - - wp_plugins = WpPlugins.aggressive_detection(wp_target, - enum_options.merge( - file: PLUGINS_FILE, - type: plugin_enumeration_type - ) - ) - - puts - if !wp_plugins.empty? - grammar = grammar_s(wp_plugins.size) - puts info("We found #{wp_plugins.size} plugin#{grammar}:") - - wp_plugins.output(wpscan_options.verbose) - else - puts info('No plugins found') - end - - end - - # Enumerate installed themes - if wpscan_options.enumerate_themes or wpscan_options.enumerate_only_vulnerable_themes or wpscan_options.enumerate_all_themes - puts - if wpscan_options.enumerate_only_vulnerable_themes - puts info('Enumerating installed themes (only ones with known vulnerabilities) ...') - theme_enumeration_type = :vulnerable - end - - if wpscan_options.enumerate_themes - puts info('Enumerating installed themes (only ones marked as popular) ...') - theme_enumeration_type = :popular - end - - if wpscan_options.enumerate_all_themes - puts info('Enumerating all themes (may take a while and use a lot of system resources) ...') - theme_enumeration_type = :all - end - puts - - wp_themes = WpThemes.aggressive_detection(wp_target, - enum_options.merge( - file: THEMES_FILE, - type: theme_enumeration_type - ) - ) - puts - if !wp_themes.empty? - grammar = grammar_s(wp_themes.size) - puts info("We found #{wp_themes.size} theme#{grammar}:") - - wp_themes.output(wpscan_options.verbose) - else - puts info('No themes found') - end - - end - - if wpscan_options.enumerate_timthumbs - puts - puts info('Enumerating timthumb files ...') - puts - - wp_timthumbs = WpTimthumbs.aggressive_detection(wp_target, - enum_options.merge( - file: TIMTHUMBS_FILE, - theme_name: wp_theme ? wp_theme.name : nil - ) - ) - puts - if !wp_timthumbs.empty? - grammar = grammar_s(wp_timthumbs.size) - puts info("We found #{wp_timthumbs.size} timthumb file#{grammar}:") - - wp_timthumbs.output(wpscan_options.verbose) - else - puts info('No timthumb files found') - end - - end - - # If we haven't been supplied a username/usernames list, enumerate them... - if !wpscan_options.username && !wpscan_options.usernames && wpscan_options.wordlist || wpscan_options.enumerate_usernames - puts - puts info('Enumerating usernames ...') - - if wp_target.has_plugin?('stop-user-enumeration') - puts warning("Stop User Enumeration plugin detected, results might be empty. However a bypass exists for v1.2.8 and below, see stop_user_enumeration_bypass.rb in #{__dir__}") - end - - wp_users = WpUsers.aggressive_detection(wp_target, - enum_options.merge( - range: wpscan_options.enumerate_usernames_range, - show_progression: false - ) - ) - - if wp_users.empty? - puts info('We did not enumerate any usernames') - - if wpscan_options.wordlist - puts 'Try supplying your own username with the --username option' - puts - exit(1) - end - else - grammar = grammar_s(wp_users.size) - puts info("We identified the following #{wp_users.size} user#{grammar}:") - wp_users.output(margin_left: ' ' * 4) - if wp_users[0].login == "admin" - puts warning("Default first WordPress username 'admin' is still used") - end - end - - else - wp_users = WpUsers.new - - # Username file? - if wpscan_options.usernames - File.open(wpscan_options.usernames).each do |username| - wp_users << WpUser.new(wp_target.uri, login: username.chomp) - end - # Single username? - else - wp_users << WpUser.new(wp_target.uri, login: wpscan_options.username) - end - end - - # Start the brute forcer - bruteforce = true - if wpscan_options.wordlist - if wp_target.has_login_protection? - protection_plugin = wp_target.login_protection_plugin() - - puts - puts warning("The plugin #{protection_plugin.name} has been detected. It might record the IP and timestamp of every failed login and/or prevent brute forcing altogether. Not a good idea for brute forcing!") - puts '[?] Do you want to start the brute force anyway ? [Y]es [N]o, default: [N]' - - bruteforce = false if wpscan_options.batch || Readline.readline !~ /^y/i - end - - if bruteforce - puts info('Starting the password brute forcer') - - begin - wp_users.brute_force( - wpscan_options.wordlist, - show_progression: true, - verbose: wpscan_options.verbose - ) - ensure - puts - wp_users.output(show_password: true, margin_left: ' ' * 2) - end - else - puts critical('Brute forcing aborted') - end - - end - - stop_time = Time.now - elapsed = stop_time - start_time - used_memory = get_memory_usage - start_memory unless windows? - - puts - puts info("Finished: #{stop_time.asctime}") - puts info("Elapsed time: #{Time.at(elapsed).utc.strftime('%H:%M:%S')}") - puts info("Requests made: #{@total_requests_done}") - puts info("Memory used: #{used_memory.bytes_to_human}") unless windows? - - # do nothing on interrupt - rescue Interrupt - exit(1) - # Error on Updating - rescue ChecksumError => e - puts critical(e.message) - - if e.file - puts critical("Current Version: #{WPSCAN_VERSION}") - puts critical('Downloaded File Content:') - puts e.file[0..500] # print first 500 chars - puts '.........' - puts e.file[-500..-1] || e.file # print last 500 chars or the whole file if it's < 500 - puts - end - - puts critical('Some hints to help you with this issue:') - puts critical('-) Try updating again using --verbose') - puts critical('-) If you see SSL/TLS related error messages you have to fix your local TLS setup') - puts critical('-) Windows is still not supported') - exit(1) - rescue => e - puts - puts critical(e.message) - - if wpscan_options && wpscan_options.verbose - puts critical('Trace:') - puts critical(e.backtrace.join("\n")) - end - exit(1) - ensure - # Make sure there was an argument - if ARGV.length != 0 - # Ensure a clean abort of Hydra - # See https://github.com/wpscanteam/wpscan/issues/461#issuecomment-42735615 - Browser.instance.hydra.abort - Browser.instance.hydra.run - end - end -end - -main() -exit($exit_code)