Compare commits

...

110 Commits

Author SHA1 Message Date
erwanlr
30f329fe43 Bumps version 2019-07-23 18:27:09 +01:00
erwanlr
4ce39951a9 Additional specs for #1374 2019-07-23 16:33:09 +01:00
ethicalhack3r
0e9eb34626 Remove Patreon link 2019-07-23 12:09:04 +02:00
erwanlr
0ff299c425 Updates UA used when updating the DB 2019-07-22 12:13:01 +01:00
erwanlr
6366258ce9 Merge branch 'df' 2019-07-20 19:11:06 +01:00
erwanlr
bca69a026e Adds DFs 2019-07-20 19:10:47 +01:00
Christian Mehlmauer
adc26ea42a ruby 2.6.3 2019-07-19 09:16:56 +02:00
Erwan
b16e8d84d7 Merge pull request #1369 from wpscanteam/dependabot/bundler/rubocop-tw-0.73.0
Update rubocop requirement from ~> 0.72.0 to ~> 0.73.0
2019-07-17 11:38:45 +02:00
dependabot-preview[bot]
5ee405d5a0 Update rubocop requirement from ~> 0.72.0 to ~> 0.73.0
Updates the requirements on [rubocop](https://github.com/rubocop-hq/rubocop) to permit the latest version.
- [Release notes](https://github.com/rubocop-hq/rubocop/releases)
- [Changelog](https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop-hq/rubocop/compare/v0.72.0...v0.73.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-17 05:28:25 +00:00
erwanlr
a5b9470636 Adds DFs 2019-07-13 11:57:18 +01:00
erwanlr
16a3d54cb6 Bumps version 2019-07-11 17:50:46 +01:00
erwanlr
9677dcd978 Makes sure the sub_dir is only checked once 2019-07-10 18:35:46 +01:00
erwanlr
17ea42f918 Updates cms_scanner dep 2019-07-10 09:17:49 +01:00
erwanlr
bd8915918d Switcing back to master 2019-07-09 15:07:42 +01:00
erwanlr
91db6773a0 Reduces --themes-threshold 2019-07-09 14:37:30 +01:00
erwanlr
f50680b61f Adds a --plugins-threshold and --themes-threshold options 2019-07-08 19:47:46 +01:00
erwanlr
3fb5d33333 Switching to dev 2019-07-08 17:34:13 +01:00
erwanlr
f70bbb2660 Switching to master 2019-07-08 14:02:38 +01:00
erwanlr
589c1ac9bb Only create Versions DF when needed 2019-07-08 13:02:29 +01:00
erwanlr
d458fa1b89 Switching to dev 2019-07-08 10:23:42 +01:00
erwanlr
dc2c99434f Switching to master 2019-07-07 12:19:05 +01:00
erwanlr
bbf36562d0 Fixes specs 2019-07-07 09:57:54 +01:00
erwanlr
c458edf3e4 Adds a note about the Readme DF 2019-07-07 08:51:29 +01:00
erwanlr
99c2aaef7a Changes some DF method names to avoid confusion with db ones 2019-07-07 08:35:41 +01:00
erwanlr
921096ca10 Adds DFs 2019-07-07 08:09:22 +01:00
erwanlr
b0fbd6fa36 Removes empty expected DF 2019-07-06 15:58:23 +01:00
erwanlr
21bd67c44f Switching to minor release 2019-07-06 15:53:00 +01:00
erwanlr
4f142985a2 Fixes #1364 2019-07-06 15:32:42 +01:00
erwanlr
bfa89b44bc Switching to dev 2019-07-06 13:04:38 +01:00
erwanlr
eba876e72b Adds DFs 2019-07-06 11:05:22 +01:00
erwanlr
f1a7413e20 Adds Theme DFs 2019-07-05 09:34:13 +01:00
erwanlr
4d32749489 Updates deps and bump version 2019-07-04 17:06:28 +01:00
erwanlr
d911a16684 Removes useless WPScan namespace 2019-07-04 16:46:33 +01:00
erwanlr
d7193bc755 Ref #1364 2019-07-04 16:33:14 +01:00
erwanlr
aee9ffdb9c Fixes #1365 2019-07-04 15:45:01 +01:00
erwanlr
1f627d5e49 Adds DFs 2019-06-29 10:51:03 +01:00
ethicalhack3r
bb67626d09 Change thimthub enum icon back to info 2019-06-28 15:04:30 +02:00
ethicalhack3r
4e0153e94a Change some enum icons to critical 2019-06-28 15:00:05 +02:00
erwanlr
065142ff19 Updates Rubocop dep 2019-06-27 08:15:54 +01:00
erwanlr
8bb6fae52f Adds DFs 2019-06-22 11:31:28 +01:00
Erwan
8cb7b81903 Merge pull request #1359 from wpscanteam/dependabot/bundler/rubocop-performance-tw-1.4.0
Update rubocop-performance requirement from ~> 1.3.0 to ~> 1.4.0
2019-06-21 13:02:00 +02:00
dependabot-preview[bot]
cb214ccda9 Update rubocop-performance requirement from ~> 1.3.0 to ~> 1.4.0
Updates the requirements on [rubocop-performance](https://github.com/rubocop-hq/rubocop-performance) to permit the latest version.
- [Release notes](https://github.com/rubocop-hq/rubocop-performance/releases)
- [Changelog](https://github.com/rubocop-hq/rubocop-performance/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop-hq/rubocop-performance/compare/v1.3.0...v1.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-21 05:41:30 +00:00
erwanlr
3fa7b96f27 Bumps version 2019-06-17 18:11:37 +01:00
erwanlr
7c8e259072 Adds DFs 2019-06-15 16:28:14 +01:00
erwanlr
743d067042 Adds DFs 2019-06-08 12:11:24 +01:00
Erwan
50ea410718 Merge pull request #1353 from wpscanteam/dependabot/bundler/webmock-tw-3.6.0
Update webmock requirement from ~> 3.5.1 to ~> 3.6.0
2019-06-05 12:50:44 +02:00
dependabot-preview[bot]
e71182aed2 Update webmock requirement from ~> 3.5.1 to ~> 3.6.0
Updates the requirements on [webmock](https://github.com/bblimke/webmock) to permit the latest version.
- [Release notes](https://github.com/bblimke/webmock/releases)
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.5.1...v3.6.0)
2019-06-05 07:53:59 +00:00
erwanlr
97f7963e0b Adds DFs 2019-06-02 14:05:44 +01:00
Erwan
6cea6a10bd Merge pull request #1352 from wpscanteam/dependabot/bundler/rubocop-tw-0.71.0
Update rubocop requirement from ~> 0.70.0 to ~> 0.71.0
2019-05-31 14:24:27 +02:00
dependabot-preview[bot]
344d41e365 Update rubocop requirement from ~> 0.70.0 to ~> 0.71.0
Updates the requirements on [rubocop](https://github.com/rubocop-hq/rubocop) to permit the latest version.
- [Release notes](https://github.com/rubocop-hq/rubocop/releases)
- [Changelog](https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop-hq/rubocop/compare/v0.70.0...v0.71.0)
2019-05-31 08:04:55 +00:00
erwanlr
597a8adfed Removes FP DF 2019-05-24 11:16:52 +01:00
erwanlr
5682e5483a Adds DFs 2019-05-24 11:06:50 +01:00
Erwan
18779edd7d Merge pull request #1349 from wpscanteam/dependabot/bundler/rubocop-tw-0.70.0
Update rubocop requirement from ~> 0.69.0 to ~> 0.70.0
2019-05-22 14:23:49 +02:00
dependabot[bot]
63aeaea77a Update rubocop requirement from ~> 0.69.0 to ~> 0.70.0
Updates the requirements on [rubocop](https://github.com/rubocop-hq/rubocop) to permit the latest version.
- [Release notes](https://github.com/rubocop-hq/rubocop/releases)
- [Changelog](https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop-hq/rubocop/compare/v0.69.0...v0.70.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-22 06:25:23 +00:00
Erwan
f51e48cb40 Merge pull request #1347 from wpscanteam/dependabot/bundler/rubocop-tw-0.69.0
Update rubocop requirement from ~> 0.68.0 to ~> 0.69.0
2019-05-14 17:50:34 +02:00
Erwan
193372c79c Adds a note about Nokogiri in the Readme 2019-05-14 14:12:28 +02:00
dependabot[bot]
34d0afe7e5 Update rubocop requirement from ~> 0.68.0 to ~> 0.69.0
Updates the requirements on [rubocop](https://github.com/rubocop-hq/rubocop) to permit the latest version.
- [Release notes](https://github.com/rubocop-hq/rubocop/releases)
- [Changelog](https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop-hq/rubocop/compare/v0.68.0...v0.69.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-14 11:26:28 +00:00
Erwan
d33a9dd56d Merge pull request #1346 from wpscanteam/dependabot/bundler/rubocop-performance-tw-1.3.0
Update rubocop-performance requirement from ~> 1.2.0 to ~> 1.3.0
2019-05-14 13:19:26 +02:00
dependabot[bot]
af2be90176 Update rubocop-performance requirement from ~> 1.2.0 to ~> 1.3.0
Updates the requirements on [rubocop-performance](https://github.com/rubocop-hq/rubocop-performance) to permit the latest version.
- [Release notes](https://github.com/rubocop-hq/rubocop-performance/releases)
- [Changelog](https://github.com/rubocop-hq/rubocop-performance/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop-hq/rubocop-performance/compare/v1.2.0...v1.3.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-14 06:21:57 +00:00
erwanlr
701fb21544 Adds DFs 2019-05-11 11:34:47 +01:00
erwanlr
c8f010d9a6 Ref #1344 2019-05-08 18:17:25 +01:00
Erwan
c1ca7580e2 Merge pull request #1343 from wpscanteam/dependabot/bundler/rubocop-performance-tw-1.2.0
Update rubocop-performance requirement from ~> 1.1.0 to ~> 1.2.0
2019-05-08 18:56:36 +02:00
dependabot[bot]
11d3c2cbf1 Update rubocop-performance requirement from ~> 1.1.0 to ~> 1.2.0
Updates the requirements on [rubocop-performance](https://github.com/rubocop-hq/rubocop-performance) to permit the latest version.
- [Release notes](https://github.com/rubocop-hq/rubocop-performance/releases)
- [Changelog](https://github.com/rubocop-hq/rubocop-performance/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop-hq/rubocop-performance/compare/v1.1.0...v1.2.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-06 06:12:47 +00:00
erwanlr
412f576aee Adds DFs 2019-05-03 11:54:25 +01:00
erwanlr
ff98a7b23b Fixes #1341 2019-05-01 19:50:43 +01:00
erwanlr
507bac8542 Merge branch 'master' of github.com:wpscanteam/wpscan 2019-04-29 15:48:07 +01:00
erwanlr
3bd6cf4805 Adds Ruby 2.6.3 to Travis 2019-04-29 15:47:55 +01:00
erwanlr
5712b31869 Updates Rubocop dep 2019-04-29 15:47:33 +01:00
Erwan
b0f9a0b18f Update issue templates 2019-04-29 15:24:22 +02:00
Erwan
f7665b460e Update issue templates 2019-04-29 15:20:44 +02:00
Erwan
100029b640 Delete old issue template 2019-04-29 15:18:10 +02:00
Erwan
2b89bddf0f Update issue templates 2019-04-29 15:17:39 +02:00
erwanlr
ca46bad8ec Bumps version 2019-04-26 11:53:00 +01:00
erwanlr
1ecd2600a3 Adds DFs 2019-04-26 10:56:26 +01:00
erwanlr
28306b126b Adds DFs 2019-04-24 17:32:25 +01:00
erwanlr
5c842e192b Updates deps 2019-04-24 12:42:18 +01:00
erwanlr
f9f307118d Adds DFs 2019-04-19 10:18:52 +01:00
erwanlr
2266fa4f4b Removes useless comment 2019-04-18 14:43:21 +01:00
erwanlr
6df2564d1a Improves Target#wordpress_hosted? 2019-04-18 14:17:00 +01:00
erwanlr
b2a62ebd26 Fixes #1335 2019-04-18 12:26:47 +01:00
erwanlr
2fca30752a Improves wp-content detection 2019-04-18 12:13:56 +01:00
erwanlr
210eced369 Typo in comments 2019-04-17 17:39:20 +01:00
erwanlr
08c574aff8 Improves detection of wp-content folder 2019-04-17 15:52:06 +01:00
Christian Mehlmauer
f4db2d65f1 fix #1309 2019-04-16 06:42:26 +02:00
erwanlr
23b02ade96 Adds DFs 2019-04-13 14:29:24 +01:00
erwanlr
71d35b16ac Adds DFs 2019-04-13 14:22:42 +01:00
erwanlr
200058c52a Adds DFs 2019-04-13 10:37:39 +01:00
erwanlr
edb5fb202a Removes check for 301 when enumerating plugins and themes 2019-04-13 08:13:38 +01:00
erwanlr
d114c25cdb Typo 2019-04-12 14:52:39 +01:00
erwanlr
64e469568b Adds message help for --wp-content-dir and --wp-plugins-dir options 2019-04-12 14:07:28 +01:00
erwanlr
c63d777372 Fixes version wrongly bumped 2019-04-12 14:00:39 +01:00
erwanlr
ae343b8cb0 Checks for wp-content directly (depends on detection-mode) when not identified passively 2019-04-12 13:55:40 +01:00
Erwan
86eb5d2d57 Merge pull request #1332 from wpscanteam/dependabot/bundler/rspec-its-tw-1.3.0
Update rspec-its requirement from ~> 1.2.0 to ~> 1.3.0
2019-04-10 10:33:27 +02:00
dependabot[bot]
b562d241db Update rspec-its requirement from ~> 1.2.0 to ~> 1.3.0
Updates the requirements on [rspec-its](https://github.com/rspec/rspec-its) to permit the latest version.
- [Release notes](https://github.com/rspec/rspec-its/releases)
- [Changelog](https://github.com/rspec/rspec-its/blob/master/Changelog.md)
- [Commits](https://github.com/rspec/rspec-its/compare/v1.2.0...v1.3.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-10 06:07:39 +00:00
erwanlr
49b1829b78 Bumps version 2019-04-08 16:58:26 +01:00
erwanlr
1a5bf4035c Update deps 2019-04-08 09:39:07 +01:00
erwanlr
f3810a1504 Bumps version 2019-04-07 17:45:29 +01:00
erwanlr
4831760c11 Merge branch '3.5.1' 2019-04-07 17:42:51 +01:00
erwanlr
f375d8991e Update deps 2019-04-07 17:35:18 +01:00
erwanlr
8145a4a3a6 Fixes #1330 2019-04-07 17:06:19 +01:00
erwanlr
12c9b49d4c Adds DFs 2019-04-06 11:34:23 +01:00
erwanlr
c8eb81161e Uses https rather than git protocols for CMSScanner dep 2019-04-05 19:53:29 +01:00
erwanlr
8ab246a66c Uses CMSScanner git dep 2019-04-05 19:48:22 +01:00
erwanlr
8dfc4797fa Handles default user_agent_list via CLI option (in CMSScanner) 2019-04-05 19:30:53 +01:00
erwanlr
7888fe1176 Uses ParsedCli 2019-04-05 16:47:14 +01:00
Erwan
8a6f3056a3 Merge pull request #1329 from wpscanteam/dependabot/bundler/rubocop-tw-0.67.1
Update rubocop requirement from ~> 0.66.0 to ~> 0.67.1
2019-04-05 11:37:00 +02:00
dependabot[bot]
5fbdf9e013 Update rubocop requirement from ~> 0.66.0 to ~> 0.67.1
Updates the requirements on [rubocop](https://github.com/rubocop-hq/rubocop) to permit the latest version.
- [Release notes](https://github.com/rubocop-hq/rubocop/releases)
- [Changelog](https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop-hq/rubocop/compare/v0.66.0...v0.67.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-05 06:16:13 +00:00
erwanlr
1da2f5e823 Sets the Target#mu_plugind to true when detected passively 2019-04-04 17:25:58 +01:00
erwanlr
888779f81b Support of Ruby 2.3 removed as its life ended 2019-04-04 15:40:21 +01:00
erwanlr
352286e497 Adds a #maybe_add_cookies to handle website requiring a specific cookie 2019-04-03 19:08:52 +01:00
300 changed files with 93966 additions and 452 deletions

View File

@@ -1,3 +1,14 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
Before submitting an issue, please make sure you fully read any potential error messages output and did some research on your own.
### Subject of the issue
Describe your issue here.
@@ -24,4 +35,4 @@ Things you have tried (where relevant):
* Update Ruby to the latest version [ ]
* Ensure you can reach the target site using cURL [ ]
* Proxied WPScan through a HTTP proxy to view the raw traffic [ ]
* Ensure you are using a supported Operating System (Linux and macOS) [ ]
* Ensure you are using a supported Operating System (Linux and macOS) [ ]

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

10
.github/ISSUE_TEMPLATE/other-issue.md vendored Normal file
View File

@@ -0,0 +1,10 @@
---
name: Other Issue
about: Create a report which is not a related to a Bug or Feature
title: ''
labels: ''
assignees: ''
---
Before submitting an issue, please make sure you fully read any potential error messages output and did some research on your own.

View File

@@ -1,5 +1,6 @@
require: rubocop-performance
AllCops:
TargetRubyVersion: 2.3
TargetRubyVersion: 2.4
Exclude:
- '*.gemspec'
- 'vendor/**/*'
@@ -9,6 +10,8 @@ LineLength:
Max: 120
MethodLength:
Max: 20
Exclude:
- 'app/controllers/enumeration/cli_options.rb'
Lint/UriEscapeUnescape:
Enabled: false
Metrics/AbcSize:
@@ -18,6 +21,8 @@ Metrics/BlockLength:
- 'spec/**/*'
Metrics/ClassLength:
Max: 150
Exclude:
- 'app/controllers/enumeration/cli_options.rb'
Metrics/CyclomaticComplexity:
Max: 8
Style/Documentation:

View File

@@ -2,20 +2,12 @@ language: ruby
sudo: false
cache: bundler
rvm:
- 2.3.0
- 2.3.1
- 2.3.2
- 2.3.3
- 2.3.4
- 2.3.5
- 2.3.6
- 2.3.7
- 2.3.8
- 2.4.1
- 2.4.2
- 2.4.3
- 2.4.4
- 2.4.5
- 2.4.6
- 2.5.0
- 2.5.1
- 2.5.2
@@ -25,6 +17,7 @@ rvm:
- 2.6.0
- 2.6.1
- 2.6.2
- 2.6.3
- ruby-head
before_install:
- "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"

View File

@@ -1,4 +1,4 @@
FROM ruby:2.6.2-alpine3.9 AS builder
FROM ruby:2.6.3-alpine AS builder
LABEL maintainer="WPScan Team <team@wpscan.org>"
ARG BUNDLER_ARGS="--jobs=8 --without test development"
@@ -19,19 +19,22 @@ RUN rake install --trace
RUN chmod -R a+r /usr/local/bundle
FROM ruby:2.6.2-alpine3.9
FROM ruby:2.6.3-alpine
LABEL maintainer="WPScan Team <team@wpscan.org>"
RUN adduser -h /wpscan -g WPScan -D wpscan
COPY --from=builder /usr/local/bundle /usr/local/bundle
RUN chown -R wpscan:wpscan /wpscan
# runtime dependencies
RUN apk add --no-cache libcurl procps sqlite-libs
WORKDIR /wpscan
USER wpscan
RUN /usr/local/bundle/bin/wpscan --update --verbose
ENTRYPOINT ["/usr/local/bundle/bin/wpscan"]

View File

@@ -2,3 +2,5 @@
source 'https://rubygems.org'
gemspec
# gem 'cms_scanner', branch: 'xxx', git: 'https://github.com/wpscanteam/CMSScanner.git'

View File

@@ -17,7 +17,6 @@
<a href="https://badge.fury.io/rb/wpscan" target="_blank"><img src="https://badge.fury.io/rb/wpscan.svg"></a>
<a href="https://travis-ci.org/wpscanteam/wpscan" target="_blank"><img src="https://travis-ci.org/wpscanteam/wpscan.svg?branch=master"></a>
<a href="https://codeclimate.com/github/wpscanteam/wpscan" target="_blank"><img src="https://codeclimate.com/github/wpscanteam/wpscan/badges/gpa.svg"></a>
<a href="https://www.patreon.com/wpscan" target="_blank"><img src="https://img.shields.io/badge/patreon-donate-green.svg"></a>
</p>
# INSTALL
@@ -30,6 +29,7 @@
- Curl >= 7.21 - Recommended: latest
- The 7.29 has a segfault
- RubyGems - Recommended: latest
- Nokogiri might require packages to be installed via your package manager depending on your OS, see https://nokogiri.org/tutorials/installing_nokogiri.html
### From RubyGems (Recommended)

View File

@@ -27,38 +27,41 @@ module WPScan
# @return [ Boolean ]
def update_db_required?
if local_db.missing_files?
raise Error::MissingDatabaseFile if parsed_options[:update] == false
raise Error::MissingDatabaseFile if ParsedCli.update == false
return true
end
return parsed_options[:update] unless parsed_options[:update].nil?
return ParsedCli.update unless ParsedCli.update.nil?
return false unless user_interaction? && local_db.outdated?
output('@notice', msg: 'It seems like you have not updated the database for some time.')
print '[?] Do you want to update now? [Y]es [N]o, default: [N]'
Readline.readline =~ /^y/i ? true : false
/^y/i.match?(Readline.readline) ? true : false
end
def update_db
output('db_update_started')
output('db_update_finished', updated: local_db.update, verbose: parsed_options[:verbose])
output('db_update_finished', updated: local_db.update, verbose: ParsedCli.verbose)
exit(0) unless parsed_options[:url]
exit(0) unless ParsedCli.url
end
def before_scan
@last_update = local_db.last_update
maybe_output_banner_help_and_version # From CMS Scanner
maybe_output_banner_help_and_version # From CMSScanner
update_db if update_db_required?
setup_cache
check_target_availability
load_server_module
check_wordpress_state
rescue Error::NotWordPress => e
target.maybe_add_cookies
raise e unless target.wordpress?(ParsedCli.detection_mode)
end
# Raises errors if the target is hosted on wordpress.com or is not running WordPress
@@ -66,14 +69,14 @@ module WPScan
def check_wordpress_state
raise Error::WordPressHosted if target.wordpress_hosted?
if Addressable::URI.parse(target.homepage_url).path =~ %r{/wp-admin/install.php$}i
if %r{/wp-admin/install.php$}i.match?(Addressable::URI.parse(target.homepage_url).path)
output('not_fully_configured', url: target.homepage_url)
exit(WPScan::ExitCode::VULNERABLE)
end
raise Error::NotWordPress unless target.wordpress?(parsed_options[:detection_mode]) || parsed_options[:force]
raise Error::NotWordPress unless target.wordpress?(ParsedCli.detection_mode) || ParsedCli.force
end
# Loads the related server module in the target
@@ -85,7 +88,7 @@ module WPScan
server = target.server || :Apache # Tries to auto detect the server
# Force a specific server module to be loaded if supplied
case parsed_options[:server]
case ParsedCli.server
when :apache
server = :Apache
when :iis

View File

@@ -7,16 +7,18 @@ module WPScan
class CustomDirectories < CMSScanner::Controller::Base
def cli_options
[
OptString.new(['--wp-content-dir DIR']),
OptString.new(['--wp-plugins-dir DIR'])
OptString.new(['--wp-content-dir DIR',
'The wp-content directory if custom or not detected, such as "wp-content"']),
OptString.new(['--wp-plugins-dir DIR',
'The plugins directory if custom or not detected, such as "wp-content/plugins"'])
]
end
def before_scan
target.content_dir = parsed_options[:wp_content_dir] if parsed_options[:wp_content_dir]
target.plugins_dir = parsed_options[:wp_plugins_dir] if parsed_options[:wp_plugins_dir]
target.content_dir = ParsedCli.wp_content_dir if ParsedCli.wp_content_dir
target.plugins_dir = ParsedCli.wp_plugins_dir if ParsedCli.wp_plugins_dir
return if target.content_dir
return if target.content_dir(ParsedCli.detection_mode)
raise Error::WpContentDirNotDetected
end

View File

@@ -7,17 +7,8 @@ module WPScan
module Controller
# Enumeration Controller
class Enumeration < CMSScanner::Controller::Base
def before_scan
DB::DynamicFinders::Plugin.create_versions_finders
DB::DynamicFinders::Theme.create_versions_finders
# Force the Garbage Collector to run due to the above method being
# quite heavy in objects allocation
GC.start
end
def run
enum = parsed_options[:enumerate] || {}
enum = ParsedCli.enumerate || {}
enum_plugins if enum_plugins?(enum)
enum_themes if enum_themes?(enum)

View File

@@ -11,7 +11,6 @@ module WPScan
end
# @return [ Array<OptParseValidator::OptBase> ]
# rubocop:disable Metrics/MethodLength
def cli_enum_choices
[
OptMultiChoices.new(
@@ -45,7 +44,6 @@ module WPScan
)
]
end
# rubocop:enable Metrics/MethodLength
# @return [ Array<OptParseValidator::OptBase> ]
def cli_plugins_opts
@@ -67,6 +65,11 @@ module WPScan
'Use the supplied mode to check plugins versions instead of the --detection-mode ' \
'or --plugins-detection modes.'],
choices: %w[mixed passive aggressive], normalize: :to_sym, default: :mixed
),
OptInteger.new(
['--plugins-threshold THRESHOLD',
'Raise an error when the number of detected plugins via known locations reaches the threshold. ' \
'Set to 0 to ignore the threshold.'], default: 100
)
]
end
@@ -91,6 +94,11 @@ module WPScan
'Use the supplied mode to check themes versions instead of the --detection-mode ' \
'or --themes-detection modes.'],
choices: %w[mixed passive aggressive], normalize: :to_sym, advanced: true
),
OptInteger.new(
['--themes-threshold THRESHOLD',
'Raise an error when the number of detected themes via known locations reaches the threshold. ' \
'Set to 0 to ignore the threshold.'], default: 20
)
]
end

View File

@@ -7,13 +7,13 @@ module WPScan
# @param [ String ] type (plugins or themes)
# @param [ Symbol ] detection_mode
#
# @return [ String ] The related enumration message depending on the parsed_options and type supplied
# @return [ String ] The related enumration message depending on the ParsedCli and type supplied
def enum_message(type, detection_mode)
return unless %w[plugins themes].include?(type)
details = if parsed_options[:enumerate][:"vulnerable_#{type}"]
details = if ParsedCli.enumerate[:"vulnerable_#{type}"]
'Vulnerable'
elsif parsed_options[:enumerate][:"all_#{type}"]
elsif ParsedCli.enumerate[:"all_#{type}"]
'All'
else
'Most Popular'
@@ -39,15 +39,15 @@ module WPScan
#
# @return [ Hash ]
def default_opts(type)
mode = parsed_options[:"#{type}_detection"] || parsed_options[:detection_mode]
mode = ParsedCli.options[:"#{type}_detection"] || ParsedCli.detection_mode
{
mode: mode,
exclude_content: parsed_options[:exclude_content_based],
exclude_content: ParsedCli.exclude_content_based,
show_progression: user_interaction?,
version_detection: {
mode: parsed_options[:"#{type}_version_detection"] || mode,
confidence_threshold: parsed_options[:"#{type}_version_all"] ? 0 : 100
mode: ParsedCli.options[:"#{type}_version_detection"] || mode,
confidence_threshold: ParsedCli.options[:"#{type}_version_all"] ? 0 : 100
}
}
end
@@ -61,7 +61,8 @@ module WPScan
def enum_plugins
opts = default_opts('plugins').merge(
list: plugins_list_from_opts(parsed_options),
list: plugins_list_from_opts(ParsedCli.options),
threshold: ParsedCli.plugins_threshold,
sort: true
)
@@ -77,7 +78,7 @@ module WPScan
plugins.each(&:version)
plugins.select!(&:vulnerable?) if parsed_options[:enumerate][:vulnerable_plugins]
plugins.select!(&:vulnerable?) if ParsedCli.enumerate[:vulnerable_plugins]
output('plugins', plugins: plugins)
end
@@ -107,7 +108,8 @@ module WPScan
def enum_themes
opts = default_opts('themes').merge(
list: themes_list_from_opts(parsed_options),
list: themes_list_from_opts(ParsedCli.options),
threshold: ParsedCli.themes_threshold,
sort: true
)
@@ -123,7 +125,7 @@ module WPScan
themes.each(&:version)
themes.select!(&:vulnerable?) if parsed_options[:enumerate][:vulnerable_themes]
themes.select!(&:vulnerable?) if ParsedCli.enumerate[:vulnerable_themes]
output('themes', themes: themes)
end
@@ -145,28 +147,28 @@ module WPScan
end
def enum_timthumbs
opts = default_opts('timthumbs').merge(list: parsed_options[:timthumbs_list])
opts = default_opts('timthumbs').merge(list: ParsedCli.timthumbs_list)
output('@info', msg: "Enumerating Timthumbs #{enum_detection_message(opts[:mode])}") if user_interaction?
output('timthumbs', timthumbs: target.timthumbs(opts))
end
def enum_config_backups
opts = default_opts('config_backups').merge(list: parsed_options[:config_backups_list])
opts = default_opts('config_backups').merge(list: ParsedCli.config_backups_list)
output('@info', msg: "Enumerating Config Backups #{enum_detection_message(opts[:mode])}") if user_interaction?
output('config_backups', config_backups: target.config_backups(opts))
end
def enum_db_exports
opts = default_opts('db_exports').merge(list: parsed_options[:db_exports_list])
opts = default_opts('db_exports').merge(list: ParsedCli.db_exports_list)
output('@info', msg: "Enumerating DB Exports #{enum_detection_message(opts[:mode])}") if user_interaction?
output('db_exports', db_exports: target.db_exports(opts))
end
def enum_medias
opts = default_opts('medias').merge(range: parsed_options[:enumerate][:medias])
opts = default_opts('medias').merge(range: ParsedCli.enumerate[:medias])
if user_interaction?
output('@info',
@@ -181,13 +183,13 @@ module WPScan
#
# @return [ Boolean ] Wether or not to enumerate the users
def enum_users?(opts)
opts[:users] || (parsed_options[:passwords] && !parsed_options[:username] && !parsed_options[:usernames])
opts[:users] || (ParsedCli.passwords && !ParsedCli.username && !ParsedCli.usernames)
end
def enum_users
opts = default_opts('users').merge(
range: enum_users_range,
list: parsed_options[:users_list]
list: ParsedCli.users_list
)
output('@info', msg: "Enumerating Users #{enum_detection_message(opts[:mode])}") if user_interaction?
@@ -198,7 +200,7 @@ module WPScan
# If the --enumerate is used, the default value is handled by the Option
# However, when using --passwords alone, the default has to be set by the code below
def enum_users_range
parsed_options[:enumerate][:users] || cli_enum_choices[0].choices[:u].validate(nil)
ParsedCli.enumerate[:users] || cli_enum_choices[0].choices[:u].validate(nil)
end
end
end

View File

@@ -18,9 +18,9 @@ module WPScan
output(
'theme',
theme: target.main_theme(
mode: parsed_options[:main_theme_detection] || parsed_options[:detection_mode]
mode: ParsedCli.main_theme_detection || ParsedCli.detection_mode
),
verbose: parsed_options[:verbose]
verbose: ParsedCli.verbose
)
end
end

View File

@@ -24,7 +24,7 @@ module WPScan
end
def run
return unless parsed_options[:passwords]
return unless ParsedCli.passwords
if user_interaction?
output('@info',
@@ -33,13 +33,13 @@ module WPScan
attack_opts = {
show_progression: user_interaction?,
multicall_max_passwords: parsed_options[:multicall_max_passwords]
multicall_max_passwords: ParsedCli.multicall_max_passwords
}
begin
found = []
attacker.attack(users, passwords(parsed_options[:passwords]), attack_opts) do |user|
attacker.attack(users, passwords(ParsedCli.passwords), attack_opts) do |user|
found << user
attacker.progress_bar.log("[SUCCESS] - #{user.username} / #{user.password}")
@@ -61,42 +61,55 @@ module WPScan
# @return [ CMSScanner::Finders::Finder ]
def attacker_from_cli_options
return unless parsed_options[:password_attack]
return unless ParsedCli.password_attack
case parsed_options[:password_attack]
case ParsedCli.password_attack
when :wp_login
WPScan::Finders::Passwords::WpLogin.new(target)
Finders::Passwords::WpLogin.new(target)
when :xmlrpc
raise Error::XMLRPCNotDetected unless xmlrpc
WPScan::Finders::Passwords::XMLRPC.new(xmlrpc)
Finders::Passwords::XMLRPC.new(xmlrpc)
when :xmlrpc_multicall
raise Error::XMLRPCNotDetected unless xmlrpc
WPScan::Finders::Passwords::XMLRPCMulticall.new(xmlrpc)
Finders::Passwords::XMLRPCMulticall.new(xmlrpc)
end
end
# @return [ Boolean ]
def xmlrpc_get_users_blogs_enabled?
if xmlrpc&.enabled? &&
xmlrpc.available_methods.include?('wp.getUsersBlogs') &&
xmlrpc.method_call('wp.getUsersBlogs', [SecureRandom.hex[0, 6], SecureRandom.hex[0, 4]])
.run.body !~ /XML\-RPC services are disabled/
true
else
false
end
end
# @return [ CMSScanner::Finders::Finder ]
def attacker_from_automatic_detection
if xmlrpc&.enabled? && xmlrpc.available_methods.include?('wp.getUsersBlogs')
if xmlrpc_get_users_blogs_enabled?
wp_version = target.wp_version
if wp_version && wp_version < '4.4'
WPScan::Finders::Passwords::XMLRPCMulticall.new(xmlrpc)
Finders::Passwords::XMLRPCMulticall.new(xmlrpc)
else
WPScan::Finders::Passwords::XMLRPC.new(xmlrpc)
Finders::Passwords::XMLRPC.new(xmlrpc)
end
else
WPScan::Finders::Passwords::WpLogin.new(target)
Finders::Passwords::WpLogin.new(target)
end
end
# @return [ Array<Users> ] The users to brute force
def users
return target.users unless parsed_options[:usernames]
return target.users unless ParsedCli.usernames
parsed_options[:usernames].reduce([]) do |acc, elem|
ParsedCli.usernames.reduce([]) do |acc, elem|
acc << Model::User.new(elem.chomp)
end
end

View File

@@ -17,15 +17,15 @@ module WPScan
end
def before_scan
WPScan::DB::DynamicFinders::Wordpress.create_versions_finders
DB::DynamicFinders::Wordpress.create_versions_finders
end
def run
output(
'version',
version: target.wp_version(
mode: parsed_options[:wp_version_detection] || parsed_options[:detection_mode],
confidence_threshold: parsed_options[:wp_version_all] ? 0 : 100,
mode: ParsedCli.wp_version_detection || ParsedCli.detection_mode,
confidence_threshold: ParsedCli.wp_version_all ? 0 : 100,
show_progression: user_interaction?
)
)

View File

@@ -14,7 +14,7 @@ module WPScan
Model::EmergencyPwdResetScript.new(
target.url(path),
confidence: res.body =~ /password/i ? 100 : 40,
confidence: /password/i.match?(res.body) ? 100 : 40,
found_by: DIRECT_ACCESS,
references: {
url: 'https://codex.wordpress.org/Resetting_Your_Password#Using_the_Emergency_Password_Reset_Script'

View File

@@ -9,11 +9,13 @@ module WPScan
def passive(_opts = {})
pattern = %r{#{target.content_dir}/mu\-plugins/}i
target.in_scope_urls(target.homepage_res) do |url|
next unless Addressable::URI.parse(url).path =~ pattern
target.in_scope_uris(target.homepage_res) do |uri|
next unless uri.path =~ pattern
url = target.url('wp-content/mu-plugins/')
target.mu_plugins = true
return Model::MuPlugins.new(
url,
confidence: 70,
@@ -33,8 +35,6 @@ module WPScan
return unless [200, 401, 403].include?(res.code)
return if target.homepage_or_404?(res)
# TODO: add the check for --exclude-content once implemented ?
target.mu_plugins = true
Model::MuPlugins.new(

View File

@@ -20,10 +20,10 @@ module WPScan
end
def passive_from_css_href(res, opts)
target.in_scope_urls(res, '//style/@src|//link/@href') do |url|
next unless Addressable::URI.parse(url).path =~ %r{/themes/([^\/]+)/style.css\z}i
target.in_scope_uris(res, '//style/@src|//link/@href') do |uri|
next unless uri.path =~ %r{/themes/([^\/]+)/style.css\z}i
return create_theme(Regexp.last_match[1], url, opts)
return create_theme(Regexp.last_match[1], uri.to_s, opts)
end
nil
end

View File

@@ -13,25 +13,15 @@ module WPScan
def initialize(plugin)
finders << PluginVersion::Readme.new(plugin)
load_specific_finders(plugin)
create_and_load_dynamic_versions_finders(plugin)
end
# Load the finders associated with the plugin
# Create the dynamic version finders related to the plugin and register them
#
# @param [ Model::Plugin ] plugin
def load_specific_finders(plugin)
module_name = plugin.classify
return unless Finders::PluginVersion.constants.include?(module_name)
mod = Finders::PluginVersion.const_get(module_name)
mod.constants.each do |constant|
c = mod.const_get(constant)
next unless c.is_a?(Class)
finders << c.new(plugin)
def create_and_load_dynamic_versions_finders(plugin)
DB::DynamicFinders::Plugin.create_versions_finders(plugin.slug).each do |finder|
finders << finder.new(plugin)
end
end
end

View File

@@ -11,7 +11,7 @@ module WPScan
# The target(plugin)#readme_url can't be used directly here
# as if the --detection-mode is passive, it will always return nil
Model::WpItem::READMES.each do |file|
target.potential_readme_filenames.each do |file|
res = target.head_and_get(file)
next unless res.code == 200 && !(numbers = version_numbers(res.body)).empty?

View File

@@ -4,7 +4,7 @@ module WPScan
module Finders
module Plugins
# Plugins finder from Dynamic Finder 'BodyPattern'
class BodyPattern < WPScan::Finders::DynamicFinder::WpItems::Finder
class BodyPattern < Finders::DynamicFinder::WpItems::Finder
DEFAULT_CONFIDENCE = 30
# @param [ Hash ] opts The options from the #passive, #aggressive methods

View File

@@ -4,7 +4,7 @@ module WPScan
module Finders
module Plugins
# Plugins finder from the Dynamic Finder 'Comment'
class Comment < WPScan::Finders::DynamicFinder::WpItems::Finder
class Comment < Finders::DynamicFinder::WpItems::Finder
DEFAULT_CONFIDENCE = 30
# @param [ Hash ] opts The options from the #passive, #aggressive methods

View File

@@ -4,7 +4,7 @@ module WPScan
module Finders
module Plugins
# Plugins finder from Dynamic Finder 'ConfigParser'
class ConfigParser < WPScan::Finders::DynamicFinder::WpItems::Finder
class ConfigParser < Finders::DynamicFinder::WpItems::Finder
DEFAULT_CONFIDENCE = 40
# @param [ Hash ] opts The options from the #passive, #aggressive methods

View File

@@ -4,7 +4,7 @@ module WPScan
module Finders
module Plugins
# Plugins finder from Dynamic Finder 'HeaderPattern'
class HeaderPattern < WPScan::Finders::DynamicFinder::WpItems::Finder
class HeaderPattern < Finders::DynamicFinder::WpItems::Finder
DEFAULT_CONFIDENCE = 30
# @param [ Hash ] opts

View File

@@ -4,7 +4,7 @@ module WPScan
module Finders
module Plugins
# Plugins finder from the Dynamic Finder 'JavascriptVar'
class JavascriptVar < WPScan::Finders::DynamicFinder::WpItems::Finder
class JavascriptVar < Finders::DynamicFinder::WpItems::Finder
DEFAULT_CONFIDENCE = 60
# @param [ Hash ] opts The options from the #passive, #aggressive methods

View File

@@ -9,7 +9,7 @@ module WPScan
# @return [ Array<Integer> ]
def valid_response_codes
@valid_response_codes ||= [200, 401, 403, 301, 500].freeze
@valid_response_codes ||= [200, 401, 403, 500].freeze
end
# @param [ Hash ] opts
@@ -19,8 +19,10 @@ module WPScan
def aggressive(opts = {})
found = []
enumerate(target_urls(opts), opts.merge(check_full_response: [200, 401, 403, 500])) do |_res, slug|
enumerate(target_urls(opts), opts.merge(check_full_response: true)) do |_res, slug|
found << Model::Plugin.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
raise Error::PluginsThresholdReached if opts[:threshold].positive? && found.size >= opts[:threshold]
end
found

View File

@@ -4,7 +4,7 @@ module WPScan
module Finders
module Plugins
# Plugins finder from Dynamic Finder 'QueryParameter'
class QueryParameter < WPScan::Finders::DynamicFinder::WpItems::Finder
class QueryParameter < Finders::DynamicFinder::WpItems::Finder
DEFAULT_CONFIDENCE = 10
def passive(_opts = {})

View File

@@ -4,7 +4,7 @@ module WPScan
module Finders
module Plugins
# Plugins finder from the Dynamic Finder 'Xpath'
class Xpath < WPScan::Finders::DynamicFinder::WpItems::Finder
class Xpath < Finders::DynamicFinder::WpItems::Finder
DEFAULT_CONFIDENCE = 40
# @param [ Hash ] opts The options from the #passive, #aggressive methods

View File

@@ -16,25 +16,15 @@ module WPScan
ThemeVersion::Style.new(theme) <<
ThemeVersion::WooFrameworkMetaGenerator.new(theme)
load_specific_finders(theme)
create_and_load_dynamic_versions_finders(theme)
end
# Load the finders associated with the theme
# Create the dynamic version finders related to the theme and register them
#
# @param [ Model::Theme ] theme
def load_specific_finders(theme)
module_name = theme.classify
return unless Finders::ThemeVersion.constants.include?(module_name)
mod = Finders::ThemeVersion.const_get(module_name)
mod.constants.each do |constant|
c = mod.const_get(constant)
next unless c.is_a?(Class)
finders << c.new(theme)
def create_and_load_dynamic_versions_finders(theme)
DB::DynamicFinders::Theme.create_versions_finders(theme.slug).each do |finder|
finders << finder.new(theme)
end
end
end

View File

@@ -9,7 +9,7 @@ module WPScan
# @return [ Array<Integer> ]
def valid_response_codes
@valid_response_codes ||= [200, 401, 403, 301, 500].freeze
@valid_response_codes ||= [200, 401, 403, 500].freeze
end
# @param [ Hash ] opts
@@ -19,8 +19,10 @@ module WPScan
def aggressive(opts = {})
found = []
enumerate(target_urls(opts), opts.merge(check_full_response: [200, 401, 403, 500])) do |_res, slug|
enumerate(target_urls(opts), opts.merge(check_full_response: true)) do |_res, slug|
found << Model::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
raise Error::ThemesThresholdReached if opts[:threshold].positive? && found.size >= opts[:threshold]
end
found

View File

@@ -7,6 +7,11 @@ module WPScan
class AuthorIdBruteForcing < CMSScanner::Finders::Finder
include CMSScanner::Finders::Finder::Enumerator
# @return [ Array<Integer> ]
def valid_response_codes
@valid_response_codes ||= [200, 301, 302]
end
# @param [ Hash ] opts
# @option opts [ Range ] :range Mandatory
#
@@ -15,7 +20,7 @@ module WPScan
found = []
found_by_msg = 'Author Id Brute Forcing - %s (Aggressive Detection)'
enumerate(target_urls(opts), opts) do |res, id|
enumerate(target_urls(opts), opts.merge(check_full_response: true)) do |res, id|
username, found_by, confidence = potential_username(res)
next unless username
@@ -49,7 +54,7 @@ module WPScan
super(opts.merge(title: ' Brute Forcing Author IDs -'))
end
def request_params
def full_request_params
{ followlocation: true }
end
@@ -78,8 +83,8 @@ module WPScan
# @return [ String, nil ] The username found
def username_from_response(res)
# Permalink enabled
target.in_scope_urls(res, '//link/@href|//a/@href') do |url|
username = username_from_author_url(url)
target.in_scope_uris(res, '//link/@href|//a/@href') do |uri|
username = username_from_author_url(uri.to_s)
return username if username
end

View File

@@ -45,12 +45,10 @@ module WPScan
def potential_usernames(res)
usernames = []
target.in_scope_urls(res, '//a/@href') do |url, node|
uri = Addressable::URI.parse(url)
target.in_scope_uris(res, '//a/@href') do |uri, node|
if uri.path =~ %r{/author/([^/\b]+)/?\z}i
usernames << [Regexp.last_match[1], 'Author Pattern', 100]
elsif uri.query =~ /author=[0-9]+/
elsif /author=[0-9]+/.match?(uri.query)
usernames << [node.text.to_s.strip, 'Display Name', 30]
end
end

View File

@@ -6,7 +6,7 @@ module WPScan
# Users disclosed from the dc:creator field in the RSS
# The names disclosed are display names, however depending on the configuration of the blog,
# they can be the same than usernames
class RSSGenerator < WPScan::Finders::WpVersion::RSSGenerator
class RSSGenerator < Finders::WpVersion::RSSGenerator
def process_urls(urls, _opts = {})
found = []

View File

@@ -57,9 +57,7 @@ module WPScan
def api_url
return @api_url if @api_url
target.in_scope_urls(target.homepage_res, "//link[@rel='https://api.w.org/']/@href").each do |url, _tag|
uri = Addressable::URI.parse(url.strip)
target.in_scope_uris(target.homepage_res, "//link[@rel='https://api.w.org/']/@href").each do |uri|
return @api_url = uri.join('wp/v2/users/').to_s if uri.path.include?('wp-json')
end

View File

@@ -12,8 +12,8 @@ module WPScan
def items_from_links(type, uniq = true)
found = []
target.in_scope_urls(target.homepage_res) do |url|
next unless url =~ item_attribute_pattern(type)
target.in_scope_uris(target.homepage_res) do |uri|
next unless uri.to_s =~ item_attribute_pattern(type)
found << Regexp.last_match[1]
end

View File

@@ -28,7 +28,7 @@ module WPScan
# @param [ WPScan::Target ] target
def initialize(target)
(%w[RSSGenerator AtomGenerator RDFGenerator] +
WPScan::DB::DynamicFinders::Wordpress.versions_finders_configs.keys +
DB::DynamicFinders::Wordpress.versions_finders_configs.keys +
%w[Readme UniqueFingerprinting]
).each do |finder_name|
finders << WpVersion.const_get(finder_name.to_sym).new(target)

View File

@@ -28,6 +28,11 @@ module WPScan
@version
end
# @return [ Array<String> ]
def potential_readme_filenames
@potential_readme_filenames ||= [*(DB::DynamicFinders::Plugin.df_data.dig(slug, 'Readme', 'path') || super)]
end
end
end
end

View File

@@ -63,7 +63,7 @@ module WPScan
def webshot_enabled?
res = Browser.get(url, params: { webshot: 1, src: "http://#{default_allowed_domains.sample}" })
res.body =~ /WEBSHOT_ENABLED == true/ ? false : true
/WEBSHOT_ENABLED == true/.match?(res.body) ? false : true
end
# @return [ Array<String> ] The default allowed domains (between the 2.0 and 2.8.13)

View File

@@ -9,11 +9,12 @@ module WPScan
include CMSScanner::Target::Platform::PHP
include CMSScanner::Target::Server::Generic
# Most common readme filenames, based on checking all public plugins and themes.
READMES = %w[readme.txt README.txt README.md readme.md Readme.txt].freeze
attr_reader :uri, :slug, :detection_opts, :version_detection_opts, :blog, :path_from_blog, :db_data
delegate :homepage_res, :xpath_pattern_from_page, :in_scope_urls, :head_or_get_params, to: :blog
delegate :homepage_res, :xpath_pattern_from_page, :in_scope_uris, :head_or_get_params, to: :blog
# @param [ String ] slug The plugin/theme slug
# @param [ Target ] blog The targeted blog
@@ -117,7 +118,7 @@ module WPScan
return @readme_url unless @readme_url.nil?
READMES.each do |path|
potential_readme_filenames.each do |path|
t_url = url(path)
return @readme_url = t_url if Browser.forge_request(t_url, blog.head_or_get_params).run.code == 200
@@ -126,6 +127,10 @@ module WPScan
@readme_url = false
end
def potential_readme_filenames
@potential_readme_filenames ||= READMES
end
# @param [ String ] path
# @param [ Hash ] params The request params
#

View File

@@ -5,7 +5,7 @@
<%= notice_icon %> Config Backup(s) Identified:
<% @config_backups.each do |config_backup| -%>
<%= info_icon %> <%= config_backup %>
<%= critical_icon %> <%= config_backup %>
<%= render('@finding', item: config_backup) -%>
<% end -%>
<% end %>

View File

@@ -5,7 +5,7 @@
<%= notice_icon %> Db Export(s) Identified:
<% @db_exports.each do |db_export| -%>
<%= info_icon %> <%= db_export %>
<%= critical_icon %> <%= db_export %>
<%= render('@finding', item: db_export) -%>
<% end -%>
<% end %>

View File

@@ -11,9 +11,10 @@
}<% unless index == last_index %>,<% end -%>
<% end -%>
<% end -%>
},
"vulnerabilities": [
<% if @item.respond_to?(:vulnerabilities) && !(vulns = @item.vulnerabilities).empty? -%>
}
<% if @item.respond_to?(:vulnerabilities) -%>
,"vulnerabilities": [
<% unless (vulns = @item.vulnerabilities).empty? -%>
<% last_index = vulns.size - 1 -%>
<% vulns.each_with_index do |v, index| -%>
{
@@ -23,4 +24,5 @@
}<% unless index == last_index -%>,<% end -%>
<% end -%>
<% end -%>
]
]
<% end -%>

View File

@@ -19,6 +19,7 @@ require 'wpscan/helper'
require 'wpscan/db'
require 'wpscan/version'
require 'wpscan/errors'
require 'wpscan/parsed_cli'
require 'wpscan/browser'
require 'wpscan/target'
require 'wpscan/finders'

View File

@@ -5,11 +5,6 @@ module WPScan
class Browser < CMSScanner::Browser
extend Actions
# @return [ String ] The path to the user agents list
def user_agents_list
@user_agents_list ||= DB_DIR.join('user-agents.txt').to_s
end
# @return [ String ]
def default_user_agent
"WPScan v#{VERSION} (https://wpscan.org/)"

View File

@@ -5,18 +5,19 @@ module WPScan
module DynamicFinders
class Base
# @return [ String ]
def self.db_file
@db_file ||= DB_DIR.join('dynamic_finders.yml').to_s
def self.df_file
@df_file ||= DB_DIR.join('dynamic_finders.yml').to_s
end
# @return [ Hash ]
def self.db_data
# true allows aliases to be loaded
@db_data ||= YAML.safe_load(File.read(db_file), [Regexp], [], true)
def self.all_df_data
@all_df_data ||= YAML.safe_load(File.read(df_file), [Regexp])
end
# @return [ Array<Symbol> ]
def self.allowed_classes
# The Readme is not put in there as it's not a Real DF, but rather using the DF system
# to get the list of potential filenames for a given slug
@allowed_classes ||= %i[Comment Xpath HeaderPattern BodyPattern JavascriptVar QueryParameter ConfigParser]
end

View File

@@ -5,8 +5,8 @@ module WPScan
module DynamicFinders
class Plugin < Base
# @return [ Hash ]
def self.db_data
@db_data ||= super['plugins'] || {}
def self.df_data
@df_data ||= all_df_data['plugins'] || {}
end
def self.version_finder_module
@@ -21,7 +21,7 @@ module WPScan
return configs unless allowed_classes.include?(finder_class)
db_data.each do |slug, finders|
df_data.each do |slug, finders|
# Quite sure better can be done with some kind of logic statement in the select
fs = if aggressive
finders.reject { |_f, c| c['path'].nil? }
@@ -48,7 +48,7 @@ module WPScan
@versions_finders_configs = {}
db_data.each do |slug, finders|
df_data.each do |slug, finders|
finders.each do |finder_name, config|
next unless config.key?('version')
@@ -73,23 +73,33 @@ module WPScan
version_finder_module.const_get(constant_name)
end
def self.create_versions_finders
versions_finders_configs.each do |slug, finders|
mod = maybe_create_module(slug)
# Create the dynamic finders related to the given slug, and return the created classes
#
# @param [ String ] slug
#
# @return [ Array<Class> ] The created classes
def self.create_versions_finders(slug)
created = []
mod = maybe_create_module(slug)
finders.each do |finder_class, config|
klass = config['class'] || finder_class
versions_finders_configs[slug]&.each do |finder_class, config|
klass = config['class'] || finder_class
# Instead of raising exceptions, skip unallowed/already defined finders
# So that, when new DF configs are put in the .yml
# users with old version of WPScan will still be able to scan blogs
# when updating the DB but not the tool
next if mod.constants.include?(finder_class.to_sym) ||
!allowed_classes.include?(klass.to_sym)
# Instead of raising exceptions, skip unallowed/already defined finders
# So that, when new DF configs are put in the .yml
# users with old version of WPScan will still be able to scan blogs
# when updating the DB but not the tool
version_finder_super_class(klass).create_child_class(mod, finder_class.to_sym, config)
end
next unless allowed_classes.include?(klass.to_sym)
created << if mod.constants.include?(finder_class.to_sym)
mod.const_get(finder_class.to_sym)
else
version_finder_super_class(klass).create_child_class(mod, finder_class.to_sym, config)
end
end
created
end
# The idea here would be to check if the class exist in

View File

@@ -5,8 +5,8 @@ module WPScan
module DynamicFinders
class Theme < Plugin
# @return [ Hash ]
def self.db_data
@db_data ||= super['themes'] || {}
def self.df_data
@df_data ||= all_df_data['themes'] || {}
end
def self.version_finder_module

View File

@@ -5,8 +5,8 @@ module WPScan
module DynamicFinders
class Wordpress < Base
# @return [ Hash ]
def self.db_data
@db_data ||= super['wordpress'] || {}
def self.df_data
@df_data ||= all_df_data['wordpress'] || {}
end
# @return [ Constant ]
@@ -30,9 +30,9 @@ module WPScan
return configs unless allowed_classes.include?(finder_class)
finders = if aggressive
db_data.reject { |_f, c| c['path'].nil? }
df_data.reject { |_f, c| c['path'].nil? }
else
db_data.select { |_f, c| c['path'].nil? }
df_data.select { |_f, c| c['path'].nil? }
end
finders.each do |finder_name, config|
@@ -48,7 +48,7 @@ module WPScan
# @return [ Hash ]
def self.versions_finders_configs
@versions_finders_configs ||= db_data.select { |_finder_name, config| config.key?('version') }
@versions_finders_configs ||= df_data.select { |_finder_name, config| config.key?('version') }
end
def self.create_versions_finders

View File

@@ -8,11 +8,11 @@ module WPScan
# /!\ Might want to also update the Enumeration#cli_options when some filenames are changed here
FILES = %w[
plugins.json themes.json wordpresses.json
timthumbs-v3.txt user-agents.txt config_backups.txt
db_exports.txt dynamic_finders.yml wp_fingerprints.json LICENSE
timthumbs-v3.txt config_backups.txt db_exports.txt
dynamic_finders.yml wp_fingerprints.json LICENSE
].freeze
OLD_FILES = %w[wordpress.db dynamic_finders_01.yml].freeze
OLD_FILES = %w[wordpress.db user-agents.txt dynamic_finders_01.yml].freeze
attr_reader :repo_directory
@@ -64,11 +64,12 @@ module WPScan
# @return [ Hash ] The params for Typhoeus::Request
# @note Those params can't be overriden by CLI options
def request_params
{
@request_params ||= {
timeout: 600,
connecttimeout: 300,
accept_encoding: 'gzip, deflate',
cache_ttl: 0
cache_ttl: 0,
headers: { 'User-Agent' => Browser.instance.default_user_agent }
}
end

View File

@@ -9,6 +9,7 @@ module WPScan
end
end
require_relative 'errors/enumeration'
require_relative 'errors/http'
require_relative 'errors/update'
require_relative 'errors/wordpress'

View File

@@ -0,0 +1,21 @@
# frozen_string_literal: true
module WPScan
module Error
class PluginsThresholdReached < Standard
def to_s
"The number of plugins detected reached the threshold of #{ParsedCli.plugins_threshold} " \
'which might indicate False Positive. It would be recommended to use the --exclude-content-based ' \
'option to ignore the bad responses.'
end
end
class ThemesThresholdReached < Standard
def to_s
"The number of themes detected reached the threshold of #{ParsedCli.themes_threshold} " \
'which might indicate False Positive. It would be recommended to use the --exclude-content-based ' \
'option to ignore the bad responses.'
end
end
end
end

View File

@@ -5,7 +5,7 @@ module WPScan
# WordPress hosted (*.wordpress.com)
class WordPressHosted < Standard
def to_s
'Scanning *.wordpress.com hosted blogs is not supported.'
'The target appears to be hosted on WordPress.com. Scanning such site is not supported.'
end
end
@@ -25,7 +25,8 @@ module WPScan
class WpContentDirNotDetected < Standard
def to_s
'Unable to identify the wp-content dir, please supply it with --wp-content-dir'
'Unable to identify the wp-content dir, please supply it with --wp-content-dir,' \
' use the --scope option or make sure the --url value given is the correct one'
end
end
end

View File

@@ -6,7 +6,7 @@ module WPScan
module Version
# Version finder using Body Pattern method. Tipically used when the response is not
# an HTML doc and Xpath can't be used
class BodyPattern < WPScan::Finders::DynamicFinder::Version::Finder
class BodyPattern < Finders::DynamicFinder::Version::Finder
# @return [ Hash ]
def self.child_class_constants
@child_class_constants ||= super().merge(PATTERN: nil, CONFIDENCE: 60)

View File

@@ -6,7 +6,7 @@ module WPScan
module Version
# Version finder in Comment, which is basically an Xpath one with a default
# Xpath of //comment()
class Comment < WPScan::Finders::DynamicFinder::Version::Xpath
class Comment < Finders::DynamicFinder::Version::Xpath
# @return [ Hash ]
def self.child_class_constants
@child_class_constants ||= super().merge(PATTERN: nil, XPATH: '//comment()')

View File

@@ -6,7 +6,7 @@ module WPScan
module Version
# Version finder using by parsing config files, such as composer.json
# and so on
class ConfigParser < WPScan::Finders::DynamicFinder::Version::Finder
class ConfigParser < Finders::DynamicFinder::Version::Finder
ALLOWED_PARSERS = [JSON, YAML].freeze
def self.child_class_constants

View File

@@ -5,7 +5,7 @@ module WPScan
module DynamicFinder
module Version
# Version finder using Header Pattern method
class HeaderPattern < WPScan::Finders::DynamicFinder::Version::Finder
class HeaderPattern < Finders::DynamicFinder::Version::Finder
# @return [ Hash ]
def self.child_class_constants
@child_class_constants ||= super().merge(HEADER: nil, PATTERN: nil, CONFIDENCE: 60)

View File

@@ -5,7 +5,7 @@ module WPScan
module DynamicFinder
module Version
# Version finder using JavaScript Variable method
class JavascriptVar < WPScan::Finders::DynamicFinder::Version::Finder
class JavascriptVar < Finders::DynamicFinder::Version::Finder
# @return [ Hash ]
def self.child_class_constants
@child_class_constants ||= super().merge(

View File

@@ -5,7 +5,7 @@ module WPScan
module DynamicFinder
module Version
# Version finder using QueryParameter method
class QueryParameter < WPScan::Finders::DynamicFinder::Version::Finder
class QueryParameter < Finders::DynamicFinder::Version::Finder
# @return [ Hash ]
def self.child_class_constants
@child_class_constants ||= super().merge(
@@ -35,15 +35,13 @@ module WPScan
def scan_response(response)
found = {}
target.in_scope_urls(response, xpath) do |url, _tag|
uri = Addressable::URI.parse(url)
target.in_scope_uris(response, xpath) do |uri|
next unless uri.path =~ path_pattern && uri.query&.match(self.class::PATTERN)
version = Regexp.last_match[:v].to_s
found[version] ||= []
found[version] << url
found[version] << uri.to_s
end
found

View File

@@ -5,7 +5,7 @@ module WPScan
module DynamicFinder
module Version
# Version finder using Xpath method
class Xpath < WPScan::Finders::DynamicFinder::Version::Finder
class Xpath < Finders::DynamicFinder::Version::Finder
# @return [ Hash ]
def self.child_class_constants
@child_class_constants ||= super().merge(

View File

@@ -4,22 +4,22 @@ module WPScan
module Finders
module DynamicFinder
module WpItemVersion
class BodyPattern < WPScan::Finders::DynamicFinder::Version::BodyPattern
class BodyPattern < Finders::DynamicFinder::Version::BodyPattern
end
class Comment < WPScan::Finders::DynamicFinder::Version::Comment
class Comment < Finders::DynamicFinder::Version::Comment
end
class ConfigParser < WPScan::Finders::DynamicFinder::Version::ConfigParser
class ConfigParser < Finders::DynamicFinder::Version::ConfigParser
end
class HeaderPattern < WPScan::Finders::DynamicFinder::Version::HeaderPattern
class HeaderPattern < Finders::DynamicFinder::Version::HeaderPattern
end
class JavascriptVar < WPScan::Finders::DynamicFinder::Version::JavascriptVar
class JavascriptVar < Finders::DynamicFinder::Version::JavascriptVar
end
class QueryParameter < WPScan::Finders::DynamicFinder::Version::QueryParameter
class QueryParameter < Finders::DynamicFinder::Version::QueryParameter
# @return [ Regexp ]
def path_pattern
# TODO: consider the target.blog.themes_dir if the target is a Theme (maybe implement a WpItem#item_dir ?)
@@ -37,7 +37,7 @@ module WPScan
end
end
class Xpath < WPScan::Finders::DynamicFinder::Version::Xpath
class Xpath < Finders::DynamicFinder::Version::Xpath
end
end
end

View File

@@ -12,23 +12,23 @@ module WPScan
end
end
class BodyPattern < WPScan::Finders::DynamicFinder::Version::BodyPattern
class BodyPattern < Finders::DynamicFinder::Version::BodyPattern
include Finder
end
class Comment < WPScan::Finders::DynamicFinder::Version::Comment
class Comment < Finders::DynamicFinder::Version::Comment
include Finder
end
class HeaderPattern < WPScan::Finders::DynamicFinder::Version::HeaderPattern
class HeaderPattern < Finders::DynamicFinder::Version::HeaderPattern
include Finder
end
class JavascriptVar < WPScan::Finders::DynamicFinder::Version::JavascriptVar
class JavascriptVar < Finders::DynamicFinder::Version::JavascriptVar
include Finder
end
class QueryParameter < WPScan::Finders::DynamicFinder::Version::QueryParameter
class QueryParameter < Finders::DynamicFinder::Version::QueryParameter
include Finder
# @return [ Hash ]

View File

@@ -6,12 +6,14 @@ rescue StandardError => e
raise "JSON parsing error in #{file} #{e}"
end
# @return [ Symbol ]
# Sanitize and classify a slug
# @note As a class can not start with a digit or underscore, a D_ is
# put as a prefix in such case. Ugly but well :x
# Not only used to classify slugs though, but Dynamic Finder names as well
# put as a prefix in such case. Ugly but well :x
# Not only used to classify slugs though, but Dynamic Finder names as well
#
# @return [ Symbol ]
def classify_slug(slug)
classified = slug.to_s.tr('-', '_').camelize.to_s
classified = slug.to_s.gsub(/[^a-z\d\-]/i, '-').gsub(/\-{1,}/, '_').camelize.to_s
classified = "D_#{classified}" if classified[0] =~ /\d/
classified.to_sym

7
lib/wpscan/parsed_cli.rb Normal file
View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
module WPScan
# To be able to use ParsedCli directly, rather than having to access it via WPscan::ParsedCli
class ParsedCli < CMSScanner::ParsedCli
end
end

View File

@@ -24,8 +24,8 @@ module WPScan
#
# @return [ Boolean ]
def wordpress?(detection_mode)
in_scope_urls(homepage_res) do |url|
return true if Addressable::URI.parse(url).path.match(WORDPRESS_PATTERN)
in_scope_uris(homepage_res) do |uri|
return true if uri.path.match(WORDPRESS_PATTERN)
end
homepage_res.html.css('meta[name="generator"]').each do |node|
@@ -36,8 +36,8 @@ module WPScan
if %i[mixed aggressive].include?(detection_mode)
%w[wp-admin/install.php wp-login.php].each do |path|
in_scope_urls(Browser.get_and_follow_location(url(path))).each do |url|
return true if Addressable::URI.parse(url).path.match(WORDPRESS_PATTERN)
in_scope_uris(Browser.get_and_follow_location(url(path))).each do |uri|
return true if uri.path.match(WORDPRESS_PATTERN)
end
end
end
@@ -45,13 +45,52 @@ module WPScan
false
end
COOKIE_PATTERNS = {
'vjs' => /createCookie\('vjs','(?<c_value>\d+)',\d+\);/i
}.freeze
# Sometimes there is a mechanism in place on the blog, which requires a specific
# cookie and value to be added to requests. Lets try to detect and add them
def maybe_add_cookies
COOKIE_PATTERNS.each do |cookie_key, pattern|
next unless homepage_res.body =~ pattern
browser = Browser.instance
cookie_string = "#{cookie_key}=#{Regexp.last_match[:c_value]}"
cookie_string += "; #{browser.cookie_string}" if browser.cookie_string
browser.cookie_string = cookie_string
# Force recheck of the homepage when retying wordpress?
# No need to clear the cache, as the request (which will contain the cookies)
# will be different
@homepage_res = nil
@homepage_url = nil
break
end
end
# @return [ String ]
def registration_url
multisite? ? url('wp-signup.php') : url('wp-login.php?action=register')
end
# @return [ Boolean ] Whether or not the target is hosted on wordpress.com
def wordpress_hosted?
uri.host =~ /\.wordpress\.com$/i ? true : false
return true if /\.wordpress\.com$/i.match?(uri.host)
unless content_dir(:passive)
pattern = %r{https?://s\d\.wp\.com#{WORDPRESS_PATTERN}}i.freeze
uris_from_page(homepage_res) do |uri|
return true if uri.to_s.match?(pattern)
end
end
false
end
# @param [ String ] username

View File

@@ -13,24 +13,36 @@ module WPScan
@plugins_dir = dir.chomp('/')
end
# @param [ Symbol ] detection_mode
# @return [ String ] The wp-content directory
def content_dir
def content_dir(detection_mode = :mixed)
unless @content_dir
escaped_url = Regexp.escape(url).gsub(/https?/i, 'https?')
pattern = %r{#{escaped_url}([\w\s\-\/]+)\/(?:themes|plugins|uploads|cache)\/}i
# scope_url_pattern is from CMSScanner::Target
pattern = %r{#{scope_url_pattern}([\w\s\-/]+)\\?/(?:themes|plugins|uploads|cache)\\?/}i
in_scope_urls(homepage_res) do |url|
return @content_dir = Regexp.last_match[1] if url.match(pattern)
in_scope_uris(homepage_res) do |uri|
return @content_dir = Regexp.last_match[1] if uri.to_s.match(pattern)
end
xpath_pattern_from_page('//script[not(@src)]', pattern, homepage_res) do |match|
# Checks for the pattern in raw JS code, as well as @content attributes of meta tags
xpath_pattern_from_page('//script[not(@src)]|//meta/@content', pattern, homepage_res) do |match|
return @content_dir = match[1]
end
unless detection_mode == :passive
return @content_dir = 'wp-content' if default_content_dir_exists?
end
end
@content_dir
end
def default_content_dir_exists?
# url('wp-content') can't be used here as the folder has not yet been identified
# and the method would try to replace it by nil which would raise an error
[200, 401, 403].include?(Browser.forge_request(uri.join('wp-content/').to_s, head_or_get_params).run.code)
end
# @return [ Addressable::URI ]
def content_uri
uri.join("#{content_dir}/")
@@ -85,23 +97,21 @@ module WPScan
themes_uri.join("#{URI.encode(slug)}/").to_s
end
# TODO: Factorise the code and the content_dir one ?
# @return [ String, False ] String of the sub_dir found, false otherwise
# @note: nil can not be returned here, otherwise if there is no sub_dir
# the check would be done each time
# the check would be done each time, which would make enumeration of
# long list of items very slow to generate
def sub_dir
unless @sub_dir
escaped_url = Regexp.escape(url).gsub(/https?/i, 'https?')
pattern = %r{#{escaped_url}(.+?)\/(?:xmlrpc\.php|wp\-includes\/)}i
return @sub_dir unless @sub_dir.nil?
in_scope_urls(homepage_res) do |url|
return @sub_dir = Regexp.last_match[1] if url.match(pattern)
end
# url_pattern is from CMSScanner::Target
pattern = %r{#{url_pattern}(.+?)/(?:xmlrpc\.php|wp\-includes/)}i
@sub_dir = false
in_scope_uris(homepage_res) do |uri|
return @sub_dir = Regexp.last_match[1] if uri.to_s.match(pattern)
end
@sub_dir
@sub_dir = false
end
# Override of the WebSite#url to consider the custom WP directories
@@ -112,9 +122,9 @@ module WPScan
def url(path = nil)
return @uri.to_s unless path
if path =~ %r{wp\-content/plugins}i
if %r{wp\-content/plugins}i.match?(path)
path = +path.gsub('wp-content/plugins', plugins_dir)
elsif path =~ /wp\-content/i
elsif /wp\-content/i.match?(path)
path = +path.gsub('wp-content', content_dir)
elsif path[0] != '/' && sub_dir
path = "#{sub_dir}/#{path}"

View File

@@ -2,5 +2,5 @@
# Version
module WPScan
VERSION = '3.5.0'
VERSION = '3.6.1'
end

View File

@@ -3,12 +3,10 @@
describe WPScan::Controller::Aliases do
subject(:controller) { described_class.new }
let(:target_url) { 'http://ex.lo/' }
let(:parsed_options) { rspec_parsed_options(cli_args) }
let(:cli_args) { "--url #{target_url}" }
before do
WPScan::Browser.reset
described_class.parsed_options = parsed_options
WPScan::ParsedCli.options = rspec_parsed_options(cli_args)
end
describe '#cli_options' do
@@ -22,14 +20,18 @@ describe WPScan::Controller::Aliases do
describe 'parsed_options' do
context 'when no --stealthy supplied' do
its(:parsed_options) { should eql parsed_options }
it 'contains the correct options' do
expect(WPScan::ParsedCli.options).to include(
detection_mode: :mixed, plugins_version_detection: :mixed
)
end
end
context 'when --stealthy supplied' do
let(:cli_args) { "#{super()} --stealthy" }
it 'contains the correct options' do
expect(controller.parsed_options).to include(
expect(WPScan::ParsedCli.options).to include(
random_user_agent: true, detection_mode: :passive, plugins_version_detection: :passive
)
end

View File

@@ -3,13 +3,11 @@
describe WPScan::Controller::Core do
subject(:core) { described_class.new }
let(:target_url) { 'http://ex.lo/' }
let(:parsed_options) { rspec_parsed_options(cli_args) }
let(:cli_args) { "--url #{target_url}" }
before do
WPScan::Browser.reset
described_class.reset
described_class.parsed_options = parsed_options
WPScan::ParsedCli.options = rspec_parsed_options(cli_args)
end
describe '#cli_options' do
@@ -140,7 +138,7 @@ describe WPScan::Controller::Core do
expect(core.formatter).to receive(:output).with('banner', hash_including(verbose: nil), 'core')
expect(core).to receive(:update_db_required?).and_return(false) unless parsed_options[:update]
expect(core).to receive(:update_db_required?).and_return(false) unless WPScan::ParsedCli.update
end
context 'when --update' do
@@ -218,7 +216,7 @@ describe WPScan::Controller::Core do
context 'when not wordpress' do
it 'raises an error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
expect(core.target).to receive(:wordpress?).twice.with(:mixed).and_return(false)
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress)
end
@@ -250,12 +248,26 @@ describe WPScan::Controller::Core do
context 'when not wordpress' do
before do
expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
end
context 'when no --force' do
it 'raises an error' do
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress)
before { expect(core.target).to receive(:maybe_add_cookies) }
context 'when no cookies added or still not wordpress after being added' do
it 'raises an error' do
expect(core.target).to receive(:wordpress?).twice.with(:mixed).and_return(false)
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress)
end
end
context 'when the added cookies solved it' do
it 'does not raise an error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false).ordered
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true).ordered
expect { core.before_scan }.to_not raise_error
end
end
end
@@ -263,6 +275,8 @@ describe WPScan::Controller::Core do
let(:cli_args) { "#{super()} --force" }
it 'does not raise any error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
expect { core.before_scan }.to_not raise_error
end
end

View File

@@ -3,12 +3,10 @@
describe WPScan::Controller::CustomDirectories do
subject(:controller) { described_class.new }
let(:target_url) { 'http://ex.lo/' }
let(:parsed_options) { rspec_parsed_options(cli_args) }
let(:cli_args) { "--url #{target_url}" }
before do
WPScan::Browser.reset
described_class.parsed_options = parsed_options
WPScan::ParsedCli.options = rspec_parsed_options(cli_args)
end
describe '#cli_options' do
@@ -21,8 +19,8 @@ describe WPScan::Controller::CustomDirectories do
end
describe '#before_scan' do
context 'when the content_dir is not found and not supply' do
before { expect(controller.target).to receive(:content_dir) }
context 'when the content_dir is not found and not supplied' do
before { expect(controller.target).to receive(:content_dir).with(:mixed) }
it 'raises an exception' do
expect { controller.before_scan }.to raise_error(WPScan::Error::WpContentDirNotDetected)
@@ -34,7 +32,7 @@ describe WPScan::Controller::CustomDirectories do
it 'does not raise any error' do
expect { controller.before_scan }.to_not raise_error
expect(controller.target.content_dir).to eq parsed_options[:wp_content_dir]
expect(controller.target.content_dir).to eq WPScan::ParsedCli.wp_content_dir
end
end
end

View File

@@ -3,16 +3,13 @@
describe WPScan::Controller::Enumeration do
subject(:controller) { described_class.new }
let(:target_url) { 'http://wp.lab/' }
let(:parsed_options) { rspec_parsed_options(cli_args) }
let(:cli_args) { "--url #{target_url}" }
before do
WPScan::Browser.reset
## For the --passwords options
allow_any_instance_of(OptParseValidator::OptPath).to receive(:check_file)
described_class.parsed_options = parsed_options
WPScan::ParsedCli.options = rspec_parsed_options(cli_args)
end
describe '#enum_message' do
@@ -73,8 +70,8 @@ describe WPScan::Controller::Enumeration do
it 'contains the correct options' do
expect(controller.cli_options.map(&:to_sym)).to eql(
%i[enumerate exclude_content_based
plugins_list plugins_detection plugins_version_all plugins_version_detection
themes_list themes_detection themes_version_all themes_version_detection
plugins_list plugins_detection plugins_version_all plugins_version_detection plugins_threshold
themes_list themes_detection themes_version_all themes_version_detection themes_threshold
timthumbs_list timthumbs_detection
config_backups_list config_backups_detection
db_exports_list db_exports_detection
@@ -105,22 +102,13 @@ describe WPScan::Controller::Enumeration do
end
end
describe '#before_scan' do
it 'creates the Dynamic Finders' do
expect(WPScan::DB::DynamicFinders::Plugin).to receive(:create_versions_finders)
expect(WPScan::DB::DynamicFinders::Theme).to receive(:create_versions_finders)
controller.before_scan
end
end
describe '#run' do
context 'when no :enumerate' do
before do
expect(controller).to receive(:enum_plugins)
expect(controller).to receive(:enum_config_backups)
expect(parsed_options[:plugins_detection]).to eql :passive
expect(WPScan::ParsedCli.plugins_detection).to eql :passive
end
it 'calls enum_plugins and enum_config_backups' do

View File

@@ -3,12 +3,10 @@
describe WPScan::Controller::PasswordAttack do
subject(:controller) { described_class.new }
let(:target_url) { 'http://ex.lo/' }
let(:parsed_options) { rspec_parsed_options(cli_args) }
let(:cli_args) { "--url #{target_url}" }
before do
WPScan::Browser.reset
described_class.parsed_options = parsed_options
WPScan::ParsedCli.options = rspec_parsed_options(cli_args)
end
describe '#cli_options' do
@@ -54,6 +52,60 @@ describe WPScan::Controller::PasswordAttack do
end
end
describe '#xmlrpc_get_users_blogs_enabled?' do
before { expect(controller.target).to receive(:xmlrpc).and_return(xmlrpc) }
context 'when xmlrpc not found' do
let(:xmlrpc) { nil }
its(:xmlrpc_get_users_blogs_enabled?) { should be false }
end
context 'when xmlrpc not enabled' do
let(:xmlrpc) { WPScan::Model::XMLRPC.new("#{target_url}xmlrpc.php") }
it 'returns false' do
expect(xmlrpc).to receive(:enabled?).and_return(false)
expect(controller.xmlrpc_get_users_blogs_enabled?).to be false
end
end
context 'when xmlrpc enabled' do
let(:xmlrpc) { WPScan::Model::XMLRPC.new("#{target_url}xmlrpc.php") }
before { expect(xmlrpc).to receive(:enabled?).and_return(true) }
context 'when wp.getUsersBlogs methods not listed' do
it 'returns false' do
expect(xmlrpc).to receive(:available_methods).and_return(%w[m1 m2])
expect(controller.xmlrpc_get_users_blogs_enabled?).to be false
end
end
context 'when wp.getUsersBlogs method listed' do
before { expect(xmlrpc).to receive(:available_methods).and_return(%w[wp.getUsersBlogs m2]) }
context 'when wp.getUsersBlogs method disabled' do
it 'returns false' do
stub_request(:post, xmlrpc.url).to_return(body: 'XML-RPC services are disabled on this site.')
expect(controller.xmlrpc_get_users_blogs_enabled?).to be false
end
end
context 'when wp.getUsersBlogs method enabled' do
it 'returns true' do
stub_request(:post, xmlrpc.url).to_return(body: 'Incorrect username or password.')
expect(controller.xmlrpc_get_users_blogs_enabled?).to be true
end
end
end
end
end
describe '#attacker' do
context 'when --password-attack provided' do
let(:cli_args) { "#{super()} --password-attack #{attack}" }
@@ -94,7 +146,7 @@ describe WPScan::Controller::PasswordAttack do
before do
expect(controller.target)
.to receive(:xmlrpc)
.and_return(WPScan::Model::XMLRPC.new("#{target_url}/xmlrpc.php"))
.and_return(WPScan::Model::XMLRPC.new("#{target_url}xmlrpc.php"))
end
context 'when single xmlrpc' do
@@ -119,73 +171,50 @@ describe WPScan::Controller::PasswordAttack do
end
context 'when automatic detection' do
before { expect(controller.target).to receive(:xmlrpc).and_return(xmlrpc) }
context 'when xmlrpc not found' do
let(:xmlrpc) { nil }
context 'when xmlrpc_get_users_blogs_enabled? is false' do
it 'returns the WpLogin' do
expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin
expect(controller.attacker.target).to be_a WPScan::Target
end
end
context 'when xmlrpc not enabled' do
let(:xmlrpc) { WPScan::Model::XMLRPC.new("#{target_url}/xmlrpc.php") }
it 'returns the WpLogin' do
expect(xmlrpc).to receive(:enabled?).and_return(false)
expect(controller).to receive(:xmlrpc_get_users_blogs_enabled?).and_return(false)
expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin
expect(controller.attacker.target).to be_a WPScan::Target
end
end
context 'when xmlrpc enabled' do
let(:xmlrpc) { WPScan::Model::XMLRPC.new("#{target_url}/xmlrpc.php") }
context 'when xmlrpc_get_users_blogs_enabled? is true' do
before do
expect(controller).to receive(:xmlrpc_get_users_blogs_enabled?).and_return(true)
before { expect(xmlrpc).to receive(:enabled?).and_return(true) }
expect(controller.target)
.to receive(:xmlrpc).and_return(WPScan::Model::XMLRPC.new("#{target_url}xmlrpc.php"))
end
context 'when wp.getUsersBlogs methods not available' do
it 'returns the WpLogin' do
expect(xmlrpc).to receive(:available_methods).and_return(%w[m1 m2])
context 'when WP version not found' do
it 'returns the XMLRPC' do
expect(controller.target).to receive(:wp_version).and_return(false)
expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin
expect(controller.attacker.target).to be_a WPScan::Target
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
end
end
context 'when wp.getUsersBlogs method evailable' do
before { expect(xmlrpc).to receive(:available_methods).and_return(%w[wp.getUsersBlogs m2]) }
context 'when WP version found' do
before { expect(controller.target).to receive(:wp_version).and_return(wp_version) }
context 'when WP version not found' do
it 'returns the XMLRPC' do
expect(controller.target).to receive(:wp_version).and_return(false)
context 'when WP < 4.4' do
let(:wp_version) { WPScan::Model::WpVersion.new('3.8.1') }
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
it 'returns the XMLRPCMulticall' do
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPCMulticall
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
end
end
context 'when WP version found' do
before { expect(controller.target).to receive(:wp_version).and_return(wp_version) }
context 'when WP >= 4.4' do
let(:wp_version) { WPScan::Model::WpVersion.new('4.4') }
context 'when WP < 4.4' do
let(:wp_version) { WPScan::Model::WpVersion.new('3.8.1') }
it 'returns the XMLRPCMulticall' do
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPCMulticall
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
end
end
context 'when WP >= 4.4' do
let(:wp_version) { WPScan::Model::WpVersion.new('4.4') }
it 'returns the XMLRPC' do
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
end
it 'returns the XMLRPC' do
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
end
end
end

View File

@@ -24,12 +24,10 @@ end
describe WPScan::Controller::WpVersion do
subject(:controller) { described_class.new }
let(:target_url) { 'http://ex.lo/' }
let(:parsed_options) { rspec_parsed_options(cli_args) }
let(:cli_args) { "--url #{target_url}" }
before do
WPScan::Browser.reset
described_class.parsed_options = parsed_options
WPScan::ParsedCli.options = rspec_parsed_options(cli_args)
end
describe '#cli_options' do
@@ -46,8 +44,8 @@ describe WPScan::Controller::WpVersion do
expect(controller.target).to receive(:wp_version)
.with(
hash_including(
mode: parsed_options[:wp_version_detection] || parsed_options[:detection_mode],
confidence_threshold: parsed_options[:wp_version_all] ? 0 : 100
mode: WPScan::ParsedCli.wp_version_detection || WPScan::ParsedCli.detection_mode,
confidence_threshold: WPScan::ParsedCli.wp_version_all ? 0 : 100
)
).and_return(stubbed)
end

View File

@@ -1,8 +1,5 @@
# frozen_string_literal: true
# If this file is tested alone (rspec path-to-this-file), then there will be an error about
# constants not being intilialized. This is due to the Dynamic Finders.
describe WPScan::Finders::PluginVersion::Base do
subject(:plugin_version) { described_class.new(plugin) }
let(:plugin) { WPScan::Model::Plugin.new(slug, target) }
@@ -15,7 +12,7 @@ describe WPScan::Finders::PluginVersion::Base do
expect(plugin_version.finders.map { |f| f.class.to_s.demodulize }).to match_array @expected
end
context 'when no related specific finders' do
context 'when no related dynamic finders' do
let(:slug) { 'spec' }
it 'contains the default finders' do
@@ -25,19 +22,13 @@ describe WPScan::Finders::PluginVersion::Base do
# Dynamic Version Finders are not tested here, they are in
# spec/lib/finders/dynamic_finder/plugin_versions_spec
context 'when specific finders' do
let(:specific) do
{
# None so far
}
end
context 'when dynamic finders' do
WPScan::DB::DynamicFinders::Plugin.versions_finders_configs.each do |plugin_slug, configs|
context "when #{plugin_slug} plugin" do
let(:slug) { plugin_slug }
it 'contains the expected finders (default + specific + the dynamic ones)' do
@expected = default_finders + [*specific[plugin_slug]] + configs.keys
it 'contains the expected finders (default + the dynamic ones)' do
@expected = default_finders + configs.keys
end
end
end

View File

@@ -13,20 +13,21 @@ describe WPScan::Finders::ThemeVersion::Base do
expect(theme_version.finders.map { |f| f.class.to_s.demodulize }).to eql @expected
end
context 'when no related specific finders' do
context 'when no related dynamic finders' do
it 'contains the default finders' do
@expected = default_finders
end
end
context 'when specific finders' do
{
}.each do |theme_slug, specific_finders|
# Dynamic Version Finders are not tested here, they are in
# spec/lib/finders/dynamic_finder/theme_versions_spec
context 'when dynamic finders' do
WPScan::DB::DynamicFinders::Theme.versions_finders_configs.each do |theme_slug, configs|
context "when #{theme_slug} theme" do
let(:slug) { theme_slug }
it 'contains the expected finders' do
@expected = default_finders + specific_finders
it 'contains the expected finders (default + the dynamic ones)' do
@expected = default_finders + configs.keys
end
end
end

View File

@@ -60,6 +60,26 @@ describe WPScan::Model::Plugin do
end
end
describe 'potential_readme_filenames' do
context 'when not set in the DF file' do
its(:potential_readme_filenames) { should eql described_class::READMES }
end
context 'when set in the DF file' do
context 'as a string' do
let(:slug) { 'photoblocks-grid-gallery' }
its(:potential_readme_filenames) { should eql %w[README.txt] }
end
context 'as an array' do
let(:slug) { 'customerlabs-actionrecorder' }
its(:potential_readme_filenames) { should eql %w[Readme.txt Readme.md] }
end
end
end
describe '#latest_version, #last_updated, #popular' do
context 'when none' do
let(:slug) { 'vulnerable-not-popular' }

View File

@@ -16,7 +16,7 @@ describe 'App::Views' do
let(:parsed_options) { { url: target_url, format: formatter.to_s.underscore.dasherize } }
before do
controller.class.parsed_options = parsed_options
WPScan::ParsedCli.options = parsed_options
# Resets the formatter to ensure the correct one is loaded
controller.class.class_variable_set(:@@formatter, nil)
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +0,0 @@
# Coments should be ignored
UA-1
UA-2

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
# Copyright (C) 2019 Jörn Lund
# This file is distributed under the same license as the ACF Dropzone plugin.
msgid ""
msgstr ""
"Project-Id-Version: ACF Dropzone 1.0.0\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/acf-dropzone\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2019-07-04T10:29:43+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.1.0\n"
"X-Domain: acf-dropzone\n"
#. Plugin Name of the plugin
msgid "ACF Dropzone"
msgstr ""
#. Plugin URI of the plugin
msgid "https://github.com/mcguffin/acf-dropzone"
msgstr ""
#. Description of the plugin
msgid "Drag and drop file upload for ACF-Fields."
msgstr ""
#. Author of the plugin
msgid "Jörn Lund"
msgstr ""
#. Author URI of the plugin
msgid "https://github.com/mcguffin"
msgstr ""
#: include/AcfDropzone/Compat/ACF.php:47
#: tmp/svn/tags/1.0.0/include/AcfDropzone/Compat/ACF.php:47
#: tmp/svn/trunk/include/AcfDropzone/Compat/ACF.php:47
#: tmp/git/include/AcfDropzone/Compat/ACF.php:47
msgid "Enable Dropzone"
msgstr ""
#: include/AcfDropzone/Compat/ACF.php:103
#: tmp/svn/tags/1.0.0/include/AcfDropzone/Compat/ACF.php:103
#: tmp/svn/trunk/include/AcfDropzone/Compat/ACF.php:103
#: tmp/git/include/AcfDropzone/Compat/ACF.php:103
msgid "Dismiss this notice."
msgstr ""
#: include/AcfDropzone/Compat/ACF.php:107
#: tmp/svn/tags/1.0.0/include/AcfDropzone/Compat/ACF.php:107
#: tmp/svn/trunk/include/AcfDropzone/Compat/ACF.php:107
#: tmp/git/include/AcfDropzone/Compat/ACF.php:107
msgid "Drop files here"
msgstr ""
#: include/AcfDropzone/Compat/ACF.php:108
#: tmp/svn/tags/1.0.0/include/AcfDropzone/Compat/ACF.php:108
#: tmp/svn/trunk/include/AcfDropzone/Compat/ACF.php:108
#: tmp/git/include/AcfDropzone/Compat/ACF.php:108
msgid "or"
msgstr ""

View File

@@ -0,0 +1,225 @@
# Copyright (C) 2019 Jörn Lund
# This file is distributed under the same license as the ACF OpenStreetMap Field plugin.
msgid ""
msgstr ""
"Project-Id-Version: ACF OpenStreetMap Field 1.0.0\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/acf-field-openstreetmap\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2019-07-05T08:37:19+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.1.0\n"
"X-Domain: acf-openstreetmap-field\n"
#. Plugin Name of the plugin
msgid "ACF OpenStreetMap Field"
msgstr ""
#. Plugin URI of the plugin
msgid "https://wordpress.org/plugins/acf-openstreetmap-field"
msgstr ""
#. Description of the plugin
msgid "A configurable OpenStreetMap Field for ACF."
msgstr ""
#. Author of the plugin
msgid "Jörn Lund"
msgstr ""
#. Author URI of the plugin
msgid "https://github.com/mcguffin"
msgstr ""
#: include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:37
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:37
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:37
#: tmp/git/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:37
msgid "OpenStreetMap Settings"
msgstr ""
#: include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:37
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:51
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:37
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:51
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:37
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:51
#: tmp/git/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:37
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:51
msgid "OpenStreetMap"
msgstr ""
#: include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:51
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:51
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:51
#: tmp/git/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:51
msgid "acf-openstreetmap-field Settings"
msgstr ""
#: include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:57
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:57
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:57
#: tmp/git/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:57
msgid "Save Settings"
msgstr ""
#: include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:86
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:86
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:86
#: tmp/git/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:86
msgid "Access Tokens"
msgstr ""
#: include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:139
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:139
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:139
#: tmp/git/include/ACFFieldOpenstreetmap/Settings/SettingsOpenStreetMap.php:139
msgid "Enter Access Tokens for various Map Tile providers."
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:125
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:125
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:125
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:125
msgid "Raw Data"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:126
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:126
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:126
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:126
msgid "Leaflet JS"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:127
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:127
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:127
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:127
msgid "iFrame (OpenStreetMap.org)"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:146
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:146
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:146
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:146
msgid "Map Appearance"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:147
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:147
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:147
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:147
msgid "Set zoom, center and select layers being displayed."
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:167
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:167
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:167
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:167
msgid "Map Position"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:168
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:179
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:168
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:179
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:168
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:179
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:168
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:179
msgid "Center the initial map"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:171
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:171
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:171
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:171
msgid "lat"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:178
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:178
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:178
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:178
msgid "Center"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:182
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:182
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:182
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:182
msgid "lng"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:190
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:190
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:190
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:190
msgid "Zoom"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:191
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:191
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:191
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:191
msgid "Set the initial zoom level"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:196
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:196
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:196
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:196
msgid "zoom"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:203
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:203
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:203
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:203
msgid "Allow layer selection"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:213
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:213
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:213
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:213
msgid "Customise the map height"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:222
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:222
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:222
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:222
msgid "Max. number of Markers"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:223
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:223
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:223
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:223
msgid "Leave empty for infinite markers"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:380
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:380
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:380
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:380
msgid "Locate Marker"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:407
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:407
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:407
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:407
msgid "Remove Marker"
msgstr ""
#: include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:734
#: tmp/svn/tags/1.0.0/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:734
#: tmp/svn/trunk/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:734
#: tmp/git/include/ACFFieldOpenstreetmap/Field/OpenStreetMap.php:734
msgid "View Larger Map"
msgstr ""

View File

@@ -0,0 +1,37 @@
# Changelog
## 1.1.6 - 19 Mar 2019
* FIX [#32](https://github.com/BeAPI/acf-options-for-polylang/issues/32) & [#40](https://github.com/BeAPI/acf-options-for-polylang/issues/40) : fix `get_field()` if an object is provided (WP Term, WP Post, WP Comment)
## 1.1.5 - 11 Dec 2018
* FIX wrong constant
## 1.1.4 - 13 Nov 2018
* Refactor by adding the Helpers class
* FEATURE [#26](https://github.com/BeAPI/acf-options-for-polylang/issues/26) : allow to precise to show or hide default values for a specific option page
* FEATURE [#21](https://github.com/BeAPI/acf-options-for-polylang/pull/21) : handle custom option id
## 1.1.3 - 2 Aug 2018
* FEATURE [#23](https://github.com/BeAPI/acf-options-for-polylang/pull/23) : requirement to php5.6 whereas namespace are 5.3
## 1.1.2 - 31 Jul 2018
* FIX [#22](https://github.com/BeAPI/acf-options-for-polylang/pull/22) : error with repeater fields default values
## 1.1.1 - 9 Mai 2018
* FIX [#15](https://github.com/BeAPI/acf-options-for-polylang/issues/15) : way requirements are checked to trigger on front / admin
## 1.1.0 - Mar 2018
* True (complet) plugin.
* Add check for ACF 5.6.
## 1.0.2 - 23 Dec 2017
* Refactor and reformat.
* Handle all options page and custom post_id.
* Now load only if ACF & Polylang are activated.
* Load later at plugins loaded.
## 1.0.1 - 19 Sep 2016
* Plugin update.
## 1.0.0 - 8 Mar 2016
* Init plugin.

View File

@@ -0,0 +1,146 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2019 Atlex
# This file is distributed under the same license as the PACKAGE package.
# Atlex developer@atlex.ru, 2019.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Admin Atlex Cloud Plugin 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-03-05 21:53+0400\n"
"PO-Revision-Date: 2019-03-20 21:53+0400\n"
"Last-Translator: ATLEX developer@atlex.ru\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#msgfmt ru_RU.pot --output-file=ru_RU.mo
msgid "Host"
msgstr "Адрес"
msgid "Cloud Adapter"
msgstr "Тип Адаптера"
msgid "Project"
msgstr "Проект"
msgid "User"
msgstr "Пользователь"
msgid "Password"
msgstr "Пароль"
msgid "Backup Container"
msgstr "Удаленный Контейнер"
msgid "Local Directory"
msgstr "Локальный Каталог"
msgid "Save"
msgstr "Сохранить"
msgid "Atlex Cloud Settings"
msgstr "Настройки Облака Атлекс"
msgid "Cloud Tools"
msgstr "Инструменты Облака"
msgid "Settings"
msgstr "Настройки"
msgid "Atlex Cloud"
msgstr "Атлекс Облако"
msgid "Atlex Settings"
msgstr "Атлекс Настройки"
msgid "Backup Batabase"
msgstr "Резервная Копия Базы Данных"
msgid "Archive Name"
msgstr "Имя Архива"
msgid "Backup"
msgstr "Резервная Копия"
msgid "Remote Archive"
msgstr "Удаленный Архив"
msgid "Restore"
msgstr "Восстановить"
msgid "Delete"
msgstr "Удалить"
msgid "Backup Wordpress Files"
msgstr "Резервная Копия Wordpress Файлов"
msgid "Wordpress Directory"
msgstr "Директория Wordpress"
msgid "Cloud Directory Name"
msgstr "Имя каталога в облаке"
msgid "Remote Directories Archive"
msgstr "Удаленный Архив Каталогов"
msgid "Download"
msgstr "Скачать"
msgid "You need configurate cloud setting for connection"
msgstr "Вам необходимо настроить параметры облака для подключения"
msgid "Loading"
msgstr "Загружается"
msgid "Do you want to delete sql archive from cloud?"
msgstr "Вы хотите удалить архив sql из облака?"
msgid "Do you want to restore database from sql archive?"
msgstr "Хотите восстановить базу данных из sql архива?"
msgid "Do you want to delete files archive from cloud?"
msgstr "Хотите удалить архив файлов из облака?"
msgid "File success downloaded to "
msgstr "Файл успешно загружен в "
msgid "Error on connection"
msgstr "Ошибка при подключении"
msgid "Successfully connected"
msgstr "Успешное подключение"
msgid "Use CDN for Mediafiles"
msgstr "Использовать CDN для Медиафайлов"
msgid "CDN Mediafiles Status"
msgstr "CDN Статус Медиафайлов"
msgid "Synchronization process"
msgstr "Процесс Синхронизации"
msgid "Cloud Public URL"
msgstr "URL-адрес public облака"
msgid "Synchronized"
msgstr "Синхронизирован"
msgid "Synchronization Off"
msgstr "Выключено"
msgid "Started Mediafiles Synchronization Process"
msgstr "Запущен процесс синхронизации медиафайлов"
msgid "Synchronize Again"
msgstr "Синхронизировать Повторно"

View File

@@ -0,0 +1,31 @@
# Copyright (C) 2019 Andy Fragen
# This file is distributed under the same license as the Admin Only Jetpack plugin.
msgid ""
msgstr ""
"Project-Id-Version: Admin Only Jetpack 1.0.0\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/admin-only-jetpack\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2019-04-26T14:33:28+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.1.0\n"
"X-Domain: admin-only-jetpack\n"
#. Plugin Name of the plugin
msgid "Admin Only Jetpack"
msgstr ""
#. Plugin URI of the plugin
msgid "https://github.com/afragen/admin-only-jetpack"
msgstr ""
#. Description of the plugin
msgid "Show Jetpack menu for Admin users only."
msgstr ""
#. Author of the plugin
msgid "Andy Fragen"
msgstr ""

View File

@@ -0,0 +1,39 @@
# Copyright (C) 2019 JSM's Adobe XMP / IPTC for WordPress
# This file is distributed under the same license as the JSM's Adobe XMP / IPTC for WordPress package.
msgid ""
msgstr ""
"Project-Id-Version: JSM's Adobe XMP / IPTC for WordPress 1.3.3\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/adobe-xmp-for-wp\n"
"POT-Creation-Date: 2019-MO-DA HO:MI+ZONE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2019-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
#: lib/shortcode.php:87
msgid "No XMP found for image ID %s."
msgstr ""
#. Plugin Name of the plugin/theme
msgid "JSM's Adobe XMP / IPTC for WordPress"
msgstr ""
#. Plugin URI of the plugin/theme
msgid "https://surniaulula.com/extend/plugins/adobe-xmp-for-wp/"
msgstr ""
#. Description of the plugin/theme
msgid ""
"Read Adobe XMP / IPTC information from Media Library and NextGEN Gallery "
"images, using a Shortcode or PHP Class Method."
msgstr ""
#. Author of the plugin/theme
msgid "JS Morisset"
msgstr ""
#. Author URI of the plugin/theme
msgid "https://surniaulula.com/"
msgstr ""

View File

@@ -0,0 +1,238 @@
# Copyright (C) 2019 Palbo Capello
# This file is distributed under the GPL-2.0+.
msgid ""
msgstr ""
"Project-Id-Version: Advanced Custom Types for Divi 1.0.0\n"
"Report-Msgid-Bugs-To: "
"https://wordpress.org/support/plugin/advanced-custom-types-divi\n"
"POT-Creation-Date: 2019-06-29 00:00:14+00:00\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2019-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-Country: United States\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: "
"__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_"
"attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n"
"X-Poedit-Basepath: ../\n"
"X-Poedit-SearchPath-0: .\n"
"X-Poedit-Bookmarks: \n"
"X-Textdomain-Support: yes\n"
"X-Generator: grunt-wp-i18n1.0.2\n"
#: advanced-custom-types-divi.php:32
msgid ""
"Advanced Custom Types for Divi was deactivated because <span "
"style='font-weight: bold;'>ACT for Divi PRO</span> is active"
msgstr ""
#: includes/class-act-divi.php:266
msgid "Settings"
msgstr ""
#: includes/class-act-divi.php:267
msgid "License"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:15
msgid "ACT Post Type Grid"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:81
msgid "View more button"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:116
msgid "Title"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:124
msgid "Body"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:127
msgid "Button"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:153
msgid "Content"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:157
msgid "Query"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:165
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:339
msgid "Layout"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:169
msgid "Card"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:182
msgid "Show title"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:185
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:201
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:233
msgid "Toggle whether mushroom will be added to the pizza."
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:189
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:205
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:237
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:396
msgid "Yes"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:190
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:206
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:238
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:397
msgid "No"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:198
msgid "Show thumbnail"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:213
msgid "Thumbnail size"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:218
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:250
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:269
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:343
msgid "Content entered here will appear inside the module."
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:230
msgid "Show content"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:245
msgid "Content length"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:265
msgid "Post type"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:276
msgid "Posts limit"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:279
msgid "Posts limit."
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:286
msgid "Posts offset"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:289
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:301
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:313
msgid "Posts offset."
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:296
msgid "Order"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:308
msgid "Order by"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:323
msgid "View more text"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:326
msgid "Post button."
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:352
msgid "Heading Level"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:356
msgid "H1"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:357
msgid "H2"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:358
msgid "H3"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:359
msgid "H4"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:360
msgid "H5"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:361
msgid "H6"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:371
msgid "Columns"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:375
msgid "1 Column"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:376
msgid "2 Columns"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:377
msgid "3 Columns"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:378
msgid "4 Columns"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:389
msgid "Card inner padding"
msgstr ""
#: includes/modules/ACTPostTypeGrid/ACTPostTypeGrid.php:392
msgid "Card inner padding."
msgstr ""
#. Plugin Name of the plugin/theme
msgid "Advanced Custom Types for Divi"
msgstr ""
#. Plugin URI of the plugin/theme
msgid "https://www.advancedcustomtypes.io"
msgstr ""
#. Description of the plugin/theme
msgid "Advanced custom types for Divi theme and Divi builder."
msgstr ""
#. Author of the plugin/theme
msgid "Palbo Capello"
msgstr ""
#. Author URI of the plugin/theme
msgid "http://capellopablo.com/"
msgstr ""

View File

@@ -0,0 +1,231 @@
# Copyright (C) 2019 Idenovasi
# This file is distributed under the same license as the Advanced Random Posts Widget package.
msgid ""
msgstr ""
"Project-Id-Version: Advanced Random Posts Widget 2.2.0\n"
"Report-Msgid-Bugs-To: https://idenovasi.com/contact/\n"
"POT-Creation-Date: 2019-03-07 16:09:37+00:00\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2019-MO-DA HO:MI+ZONE\n"
"Last-Translator: Idenovasi\n"
"Language-Team: Idenovasi\n"
"X-Generator: grunt-wp-i18n 1.0.3\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Poedit-Basepath: ..\n"
"X-Poedit-Language: English\n"
"X-Poedit-Country: UNITED STATES\n"
"X-Poedit-SourceCharset: utf-8\n"
"X-Poedit-SearchPath-0: .\n"
"X-Poedit-KeywordsList: "
"__;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c;_nc:4c,1,2;_"
"x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
"X-Textdomain-Support: yes\n"
#: includes/form.php:48
msgid "Title"
msgstr ""
#: includes/form.php:55
msgid "Title URL"
msgstr ""
#: includes/form.php:62
msgid "CSS Class"
msgstr ""
#: includes/form.php:69
msgid "HTML or text before the random posts"
msgstr ""
#: includes/form.php:76
msgid "HTML or text after the random posts"
msgstr ""
#: includes/form.php:88
msgid "Ignore sticky posts"
msgstr ""
#: includes/form.php:94
msgid "Number of posts to show"
msgstr ""
#: includes/form.php:97
msgid "to show all posts."
msgstr ""
#: includes/form.php:102
msgid "Offset"
msgstr ""
#: includes/form.php:105
msgid "The number of posts to skip"
msgstr ""
#: includes/form.php:110
msgid "Post type"
msgstr ""
#: includes/form.php:121
msgid "Post status"
msgstr ""
#: includes/form.php:136
msgid "Limit to Category"
msgstr ""
#: includes/form.php:152
msgid "Limit to Tag"
msgstr ""
#: includes/form.php:168
msgid "Limit to Taxonomy"
msgstr ""
#: includes/form.php:171
msgid "Ex: category=1,2,4&amp;post_tag=6,12"
msgstr ""
#: includes/form.php:172
msgid "Available: "
msgstr ""
#: includes/form.php:184
msgid "Display thumbnail"
msgstr ""
#: includes/form.php:190
msgid "Thumbnail Size "
msgstr ""
#: includes/form.php:197
msgid "Please read %1$sFAQ%2$s for more information."
msgstr ""
#: includes/form.php:203
msgid "Use custom thumbnail sizes"
msgstr ""
#: includes/form.php:209
msgid "Width & Height"
msgstr ""
#: includes/form.php:217
msgid "Thumbnail Alignment"
msgstr ""
#: includes/form.php:220
msgid "Left"
msgstr ""
#: includes/form.php:221
msgid "Right"
msgstr ""
#: includes/form.php:222
msgid "Center"
msgstr ""
#: includes/form.php:227
msgid ""
"Your theme does not support Post Thumbnail feature, please go to "
"%1$shttp://codex.wordpress.org/Post_Thumbnails%2$s to read more info and "
"how to activate it in your theme."
msgstr ""
#: includes/form.php:237
msgid "Display full post"
msgstr ""
#: includes/form.php:244
msgid "Display excerpt"
msgstr ""
#: includes/form.php:250
msgid "Excerpt Length"
msgstr ""
#: includes/form.php:258
msgid "Display Date"
msgstr ""
#: includes/form.php:265
msgid "Display Modified Date"
msgstr ""
#: includes/form.php:272
msgid "Use Relative Date. eg: 5 days ago"
msgstr ""
#: includes/form.php:282
msgid "Custom CSS"
msgstr ""
#: includes/form.php:285
msgid "You can find the plugin css selector on %1$sFAQ page%2$s."
msgstr ""
#: includes/functions.php:14 includes/widget.php:27
msgid "Random Posts"
msgstr ""
#: includes/posts.php:101 includes/posts.php:107
msgid "%s ago"
msgstr ""
#: includes/widget.php:17
msgid ""
"An advanced widget that gives you total control over the output of the "
"random posts."
msgstr ""
#. Plugin Name of the plugin/theme
msgid "Advanced Random Posts Widget"
msgstr ""
#. Plugin URI of the plugin/theme
msgid "https://github.com/idenovasi/advanced-random-posts-widget"
msgstr ""
#. Description of the plugin/theme
msgid "Easily to display advanced random posts via shortcode or widget."
msgstr ""
#. Author of the plugin/theme
msgid "Idenovasi"
msgstr ""
#. Author URI of the plugin/theme
msgid "https://idenovasi.com/"
msgstr ""
#: includes/form.php:34
msgctxt "widget tab name"
msgid "General"
msgstr ""
#: includes/form.php:35
msgctxt "widget tab name"
msgid "Posts"
msgstr ""
#: includes/form.php:36
msgctxt "widget tab name"
msgid "Taxonomy"
msgstr ""
#: includes/form.php:37
msgctxt "widget tab name"
msgid "Thumbnail"
msgstr ""
#: includes/form.php:38
msgctxt "widget tab name"
msgid "Extras"
msgstr ""
#: includes/form.php:39
msgctxt "widget tab name"
msgid "Custom CSS"
msgstr ""

View File

@@ -0,0 +1,49 @@
msgid ""
msgstr ""
"Project-Id-Version: xq-xe-xt-xy 1.0\n"
"POT-Creation-Date: 2018-07-11 09:44+0300\n"
"PO-Revision-Date: 2018-07-11 09:44+0300\n"
"Last-Translator: \n"
"Language-Team: Marko Maksym\n"
"Language: uk_UA\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.0.6\n"
"X-Poedit-Basepath: ../includes\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Poedit-KeywordsList: __;_e\n"
"X-Poedit-SearchPath-0: .\n"
#: admin/class-admin-main.php:66
msgid "Title of the page"
msgstr ""
#: admin/class-admin-main.php:66
msgid "Link Name"
msgstr ""
#: admin/class-admin-main.php:69
msgid "Submenu title"
msgstr ""
#: admin/class-admin-main.php:69
msgid "Submenu item"
msgstr ""
#: admin/templates/index.php:8
msgid "Settings Page"
msgstr ""
#: admin/templates/main_module_menu.php:10
msgid "Main page"
msgstr ""
#: admin/templates/main_module_menu.php:13 admin/templates/page1.php:8
msgid "Page 1"
msgstr ""
#: admin/templates/main_module_menu.php:16 admin/templates/page2.php:8
msgid "Page 2"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
1.0.0
- Initial release
1.0.2
- Fixed issues with the chrome extension
- Simpliy way to connect your store to the chrome extension

View File

@@ -0,0 +1,9 @@
v1.1.1
- Fix: PHP Notice for address fixed.
v1.1.0
- New: Add support for full FontAwesome library in widgets.
- Fix: JS error in the WordPress admin panel causing errors in
v1.0.0
- Initial release

View File

@@ -0,0 +1,34 @@
Changelog
=========
#### 1.0.1 - May 10, 2019
**Fixed**
- AffiliateWP integration subscribing the wrong user if affiliate ID differs from user ID.
- Broken url
**Improvements**
- Test by latest wordpress 5.2
#### 1.0.0 - September 21, 2018
**Changes**
- Change module name from AvangEmail to AvangPress
- Change logo
**Additions**
- Fix bug on detect connection
- Fix bug saved list to database.
#### 0.0.1 - August 8, 2018
**Improvements**
- Init project based on AvangPress for wordpress plugin
**Additions**
- Add AvangPress php api to project.

View File

@@ -0,0 +1,18 @@
{
"name": "awesome-hooks",
"version": "0.0.2",
"main": "Gruntfile.js",
"author": "Surror",
"devDependencies": {
"grunt": "^1.0.1",
"grunt-contrib-clean": "^1.1.0",
"grunt-contrib-compress": "^1.4.3",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-cssmin": "^2.2.1",
"grunt-contrib-uglify": "^3.3.0",
"grunt-postcss": "^0.9.0",
"grunt-rtlcss": "^2.0.1",
"grunt-wp-i18n": "~1.0.0"
}
}

View File

@@ -0,0 +1,9 @@
# Changelog
## 1.0.1
- Updated readme
## 1.0.0
- Initial

View File

@@ -0,0 +1,135 @@
# Copyright (C) 2019 Benjamin Lu
# This file is distributed under the same license as the Backdrop Post Types plugin.
msgid ""
msgstr ""
"Project-Id-Version: Backdrop Post Types 1.0.0\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/backdrop-post-types\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2019-04-16T18:19:05+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.1.0\n"
"X-Domain: backdrop-post-types\n"
#. Plugin Name of the plugin
msgid "Backdrop Post Types"
msgstr ""
#. Description of the plugin
msgid "Backdrop Post Types registers post types of your choice."
msgstr ""
#. Author of the plugin
msgid "Benjamin Lu"
msgstr ""
#. Author URI of the plugin
msgid "https://benjlu.com"
msgstr ""
#. Translators: a single label for a post type
#: includes/register-post-type.php:75
msgid "Add New %s"
msgstr ""
#. Translators: a single label for a post type
#: includes/register-post-type.php:78
msgid "Add New %s Item"
msgstr ""
#. Translators: a single label for a post type
#: includes/register-post-type.php:81
msgid "Edit %s Item"
msgstr ""
#. Translators: a single label for a post type
#: includes/register-post-type.php:87
msgid "View %s Item"
msgstr ""
#. Translators: a single label for a post type
#: includes/register-post-type.php:90
msgid "Search %s Item"
msgstr ""
#: includes/register-post-type.php:92
#: includes/register-post-type.php:135
msgid "Not Found"
msgstr ""
#: includes/register-post-type.php:93
msgid "Not Found in Trash"
msgstr ""
#: includes/register-post-type.php:95
msgid "Parent Item: "
msgstr ""
#: includes/register-post-type.php:119
msgctxt "Taxonomy General Name"
msgid "Categories"
msgstr ""
#: includes/register-post-type.php:120
msgctxt "Taxonomy Singular Name"
msgid "Category"
msgstr ""
#: includes/register-post-type.php:121
msgid "Categories"
msgstr ""
#: includes/register-post-type.php:122
msgid "All Categories"
msgstr ""
#: includes/register-post-type.php:123
msgid "Parent Category"
msgstr ""
#: includes/register-post-type.php:124
msgid "Parent Category:"
msgstr ""
#: includes/register-post-type.php:125
msgid "New Category Name"
msgstr ""
#: includes/register-post-type.php:126
msgid "Add New Category"
msgstr ""
#: includes/register-post-type.php:127
msgid "Edit Categories"
msgstr ""
#: includes/register-post-type.php:128
msgid "Update Categories"
msgstr ""
#: includes/register-post-type.php:129
msgid "View Categories"
msgstr ""
#: includes/register-post-type.php:130
msgid "Separate categories with commas"
msgstr ""
#: includes/register-post-type.php:131
msgid "Add or remove categories"
msgstr ""
#: includes/register-post-type.php:132
msgid "Choose from the most used"
msgstr ""
#: includes/register-post-type.php:133
msgid "Popular Categories"
msgstr ""
#: includes/register-post-type.php:134
msgid "Search Categories"
msgstr ""

View File

@@ -0,0 +1,82 @@
# Copyright (C) 2019 Applelo
# This file is distributed under the GPL-3.0+.
msgid ""
msgstr ""
"Project-Id-Version: Better Admin Users Search 1.0.0\n"
"Report-Msgid-Bugs-To: "
"http://wordpress.org/support/plugin/better-admin-users-search\n"
"POT-Creation-Date: 2019-04-06 23:45:45+00:00\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2019-4-6 23:45+240\n"
"Last-Translator: Applelo boubaultlois@gmail.com\n"
"Language-Team: Applelo boubaultlois@gmail.com\n"
"Language: en_US\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-Country: United States\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: "
"__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_"
"attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n"
"X-Poedit-Basepath: ../\n"
"X-Poedit-SearchPath-0: .\n"
"X-Poedit-Bookmarks: \n"
"X-Textdomain-Support: yes\n"
"X-Generator: grunt-wp-i18n 1.0.3\n"
#: better-admin-users-search.php:33
msgid "Settings"
msgstr ""
#: includes/class-better-admin-users-search-admin-page.php:34
msgid "Default search values"
msgstr ""
#: includes/class-better-admin-users-search-admin-page.php:35
msgid "Default values used by WordPress to do the search"
msgstr ""
#: includes/class-better-admin-users-search-admin-page.php:47
msgid "For you, this data is \"%s\""
msgstr ""
#: includes/class-better-admin-users-search-admin-page.php:54
msgid "Additionals metas"
msgstr ""
#: includes/class-better-admin-users-search-admin-page.php:55
msgid "Add additional user metas to the admin user search"
msgstr ""
#: includes/class-better-admin-users-search-admin-page.php:55
msgid "Note: Some metas won't work because their are not string."
msgstr ""
#: includes/class-better-admin-users-search-admin-page.php:63
msgid "User meta(s)"
msgstr ""
#: includes/class-better-admin-users-search-admin-page.php:65
msgid "Select metas you want to add to your search."
msgstr ""
#. Plugin Name of the plugin/theme
msgid "Better Admin Users Search"
msgstr ""
#. Plugin URI of the plugin/theme
msgid "https://github.com/Applelo/Better-Admin-Users-Search"
msgstr ""
#. Description of the plugin/theme
msgid "A plugin to improve users admin search"
msgstr ""
#. Author of the plugin/theme
msgid "Applelo"
msgstr ""
#. Author URI of the plugin/theme
msgid "https://lois-boubault.me/"
msgstr ""

View File

@@ -0,0 +1,9 @@
# Better Reviews for WooCommerce Change Log
All notable changes to this project will be documented in this file, according to [the Keep a Changelog standards](http://keepachangelog.com/).
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.1.0]
* Initial public release.

Some files were not shown because too many files have changed in this diff Show More