Compare commits

...

157 Commits

Author SHA1 Message Date
erwanlr
f23d0c0157 Bumps version 2020-03-13 16:58:35 +01:00
erwanlr
a9a38edf24 Remove cache action from build 2020-03-13 16:06:33 +01:00
erwanlr
a5534f1e49 Merge branch 'master' of github.com:wpscanteam/wpscan 2020-03-13 16:04:11 +01:00
erwanlr
1c6469f384 Updates deps 2020-03-13 16:03:59 +01:00
erwanlr
8cfdbc1196 Adds DF 2020-03-13 16:03:21 +01:00
Erwan
88737ca6ea Fixes error with reference when debug log identified 2020-03-13 08:12:35 +01:00
Erwan
45bebc60bd Fixes typo in Readme 2020-03-12 22:25:23 +01:00
Erwan
4f7dec4635 Fixes detection of Users via WP JSON when blog uses basic auth 2020-03-12 13:12:40 +01:00
erwanlr
98739cce5a Adds DF 2020-03-10 20:45:08 +01:00
erwanlr
0bfbfacc27 Fixes #1465 2020-03-10 20:31:42 +01:00
erwanlr
73cd862e83 Bumps version 2020-03-09 20:02:44 +01:00
erwanlr
3305e9b74f Adds DFs 2020-03-09 19:24:43 +01:00
erwanlr
c37ec0e8d0 Updates deps 2020-03-09 18:11:47 +01:00
erwanlr
0b005477c1 Adds additional message when checksums mismatch during an update 2020-03-08 20:48:01 +01:00
erwanlr
a1467f8dac Merge branch 'dfs' 2020-03-07 14:56:23 +01:00
erwanlr
40d2c34347 Adds DFs 2020-03-07 14:56:10 +01:00
Erwan
528270e767 Updates Target#wordpress_from_meta_comments_or_scripts Xpath check 2020-03-06 16:17:40 +01:00
erwanlr
f4a04b2387 Adds DFs 2020-03-03 18:54:41 +01:00
erwanlr
14ed6ae109 Fixes #1461 2020-03-02 15:34:51 +01:00
erwanlr
4fd43694ae Typo 2020-03-02 11:57:37 +01:00
erwanlr
552d731e6a Updates Readme to reflect #1460 2020-03-02 11:56:42 +01:00
erwanlr
49ac3ef528 Supports loading api token from ENV, Fixes #1460 2020-03-02 11:45:50 +01:00
erwanlr
4379313f12 Bumps version 2020-02-29 14:24:53 +01:00
erwanlr
3901949f36 Updates deps 2020-02-29 13:27:52 +01:00
erwanlr
a3d8593fed Adds DFs 2020-02-29 12:28:55 +01:00
erwanlr
7c5baeb9c7 Adds DF 2020-02-26 10:55:06 +01:00
erwanlr
c692db5f85 Adds DFs 2020-02-24 13:29:13 +01:00
erwanlr
9130196ffc Runs rubocop before rspec 2020-02-19 14:38:31 +01:00
erwanlr
dad4a65118 Adds Coveralls GH Action 2020-02-19 14:16:31 +01:00
Erwan
4c34c2feb7 Merge pull request #1457 from wpscanteam/dependabot/bundler/rubocop-tw-0.80.0
Update rubocop requirement from ~> 0.79.0 to ~> 0.80.0
2020-02-19 12:32:39 +01:00
dependabot-preview[bot]
23522f7775 Update rubocop requirement from ~> 0.79.0 to ~> 0.80.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.79.0...v0.80.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-19 05:23:43 +00:00
Christian Mehlmauer
82c61398ba change name 2020-02-17 07:32:20 +01:00
Christian Mehlmauer
02871050a6 change step names 2020-02-17 06:34:39 +01:00
Christian Mehlmauer
7d3b1fea6b ruby-head not supported 2020-02-17 06:32:18 +01:00
Christian Mehlmauer
24917fa2a6 wrong key 2020-02-17 06:29:14 +01:00
Christian Mehlmauer
de3d8e4a23 Use a build matrix 2020-02-17 06:28:09 +01:00
erwanlr
1502845d65 Adds DFs 2020-02-15 13:20:54 +01:00
erwanlr
af3f10f74e Reduces time to detect the sub_dir when a lot of urls 2020-02-13 20:07:25 +00:00
erwanlr
c100372b31 Reduces time to detect non WP sites 2020-02-13 19:15:30 +00:00
erwanlr
72d699b39a Adds more improvements re passive scanning when there are a lot of urls 2020-02-13 15:36:42 +00:00
erwanlr
7d2b8a2a8b Reduces time to detect non WP sites when there are a lof of links in pages 2020-02-12 19:50:00 +00:00
erwanlr
8729c68e22 Removes useless params set 2020-02-11 16:39:01 +00:00
erwanlr
e2d48bedd9 Better fix for #1451, adds target IP address to output, ref #1088 2020-02-11 16:28:59 +00:00
erwanlr
6b241ce9b3 Avoids merging CLI params when calling VulnAPI - Ref #1451 2020-02-11 09:14:14 +00:00
erwanlr
1b68bdb36c Bumps version 2020-02-09 13:31:40 +00:00
erwanlr
fb82538441 Fixes #1451 2020-02-09 12:40:48 +00:00
erwanlr
2709d0869a Adds DFs 2020-02-08 10:28:19 +00:00
erwanlr
343f87bbe7 Adds DFs 2020-02-01 10:02:38 +00:00
erwanlr
ecbfc6004c Adds DFs 2020-01-25 12:28:16 +00:00
erwanlr
c57eecc81b Adds DF 2020-01-23 12:30:27 +00:00
erwanlr
7ea14dc03f Adds DF 2020-01-23 11:15:28 +00:00
erwanlr
4340d27258 Bumps version 2020-01-21 16:14:26 +00:00
erwanlr
e911be8f14 Removes ruby 2.7.0 from failure matrix 2020-01-21 16:12:38 +00:00
erwanlr
a4c650cdff Fixes incorrect RDF URLs detection 2020-01-21 15:06:29 +00:00
erwanlr
31a58f8a8f Fixes rare crash 2020-01-21 14:47:17 +00:00
erwanlr
ba4f15f111 Adds DFs 2020-01-18 11:20:43 +00:00
Erwan
206a913eb9 Merge pull request #1447 from wpscanteam/dependabot/bundler/webmock-tw-3.8.0
Update webmock requirement from ~> 3.7.0 to ~> 3.8.0
2020-01-16 10:17:09 +01:00
dependabot-preview[bot]
21ba490073 Update webmock requirement from ~> 3.7.0 to ~> 3.8.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.7.0...v3.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-16 05:23:09 +00:00
erwanlr
2a29e2ed95 Adds DFs 2020-01-11 19:54:12 +00:00
Erwan
9517d14fd3 Fixes rubocop offence 2020-01-10 20:06:33 +01:00
Erwan
3deaa896df Fix rubocop typo 2020-01-10 19:28:01 +01:00
Erwan
c117007dc0 Merge pull request #1445 from wpscanteam/dependabot/bundler/rubocop-tw-0.79.0
Update rubocop requirement from ~> 0.78.0 to ~> 0.79.0
2020-01-07 08:53:56 +01:00
dependabot-preview[bot]
50baa238b9 Update rubocop requirement from ~> 0.78.0 to ~> 0.79.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.78.0...v0.79.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-07 05:21:29 +00:00
erwanlr
0e2d771660 Adds DFs 2020-01-04 12:17:51 +00:00
erwanlr
32b4670755 Bumps version 2020-01-02 15:28:33 +00:00
erwanlr
4a032d5e12 Merge branch 'ruby-2.7' 2020-01-02 14:53:46 +00:00
erwanlr
5887fede15 Updates deps 2020-01-02 13:53:28 +00:00
erwanlr
ad4eeb9f81 Fixes specs 2020-01-02 13:29:30 +00:00
erwanlr
a62c16d7cc Fixes Rubocop warning 2020-01-02 13:04:01 +00:00
erwanlr
e766e7392a Updates CMScanner dep 2020-01-02 12:52:03 +00:00
erwanlr
025c9c24ca Fixes GH Action 2020-01-02 12:51:23 +00:00
erwanlr
ab052add27 Allows Travis to fail on ruby-2.7 2019-12-28 13:14:19 +00:00
erwanlr
15cb99977b Fixes #1444 2019-12-28 13:10:57 +00:00
erwanlr
82d5af926f Adds Ruby 2.7.0 to Travis 2019-12-28 12:27:20 +00:00
erwanlr
76f73f3dc8 Adds DFs 2019-12-28 11:38:10 +00:00
erwanlr
575b22320e Merge branch 'df' 2019-12-21 10:49:32 +00:00
erwanlr
d20c07dc85 Adds DFs 2019-12-21 10:49:11 +00:00
erwanlr
f89071b87a Adds DFs, Updates rspec behaviour regarding --fail-fast 2019-12-20 15:47:56 +00:00
erwanlr
8b4e90f285 Updates deps + fixes travis 2019-12-19 13:56:06 +00:00
erwanlr
9c4f57c786 Adds DFs 2019-12-19 13:55:21 +00:00
erwanlr
902ec24b77 Adds DFs 2019-12-19 07:55:39 +00:00
erwanlr
7eba77fa63 Displays status code for KnownLocation finders 2019-12-15 09:00:30 +00:00
erwanlr
0753bbf7b3 Adds DF 2019-12-15 08:47:47 +00:00
erwanlr
6b2333614a Adds DFs 2019-12-14 12:14:37 +00:00
erwanlr
80b7f458f5 Fixes #1435 2019-12-08 10:34:18 +00:00
erwanlr
dbd8e59cf4 Typo 2019-12-07 15:46:31 +00:00
erwanlr
9948230ea0 Adds Dfs 2019-12-07 15:40:40 +00:00
Erwan
e2c858ac69 Merge pull request #1434 from crweiner/api-link
Fix links to API signup page
2019-12-03 13:37:55 +01:00
chandler
bac8b613e6 Fix links to API signup page 2019-12-02 17:03:36 -05:00
erwanlr
abbae15c6f Adds DFs 2019-11-30 12:47:32 +00:00
erwanlr
1548e8bfc1 Updates DFs 2019-11-28 20:19:25 +00:00
erwanlr
dc8cf3fc34 Disables a DF causing FP when checking the WP version 2019-11-28 17:15:05 +00:00
Erwan
c3cd815567 Merge pull request #1433 from wpscanteam/dependabot/bundler/rubocop-tw-0.77.0
Update rubocop requirement from ~> 0.76.0 to ~> 0.77.0
2019-11-28 08:50:50 +01:00
dependabot-preview[bot]
ce543b9384 Update rubocop requirement from ~> 0.76.0 to ~> 0.77.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.76.0...v0.77.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-28 05:21:09 +00:00
Christian Mehlmauer
9755c8cf42 Delete rubocop.yml 2019-11-26 23:33:52 +01:00
Christian Mehlmauer
434a210fb5 Update and rename rspec.yml to ruby.yml 2019-11-26 23:33:37 +01:00
Christian Mehlmauer
587602665a Update rubocop.yml 2019-11-26 23:29:30 +01:00
Christian Mehlmauer
bfec63df41 Update rspec.yml 2019-11-26 23:26:35 +01:00
Christian Mehlmauer
3b150df1af Update rspec.yml 2019-11-26 23:25:36 +01:00
Christian Mehlmauer
f24ecf0537 Update rubocop.yml 2019-11-26 23:23:13 +01:00
Christian Mehlmauer
9ddecbcc0a Update and rename ruby.yml to rspec.yml 2019-11-26 23:22:46 +01:00
Christian Mehlmauer
947bb8d3d5 Update ruby.yml 2019-11-26 23:18:33 +01:00
Christian Mehlmauer
30cbf87b35 Update gempush.yml 2019-11-26 23:14:53 +01:00
Christian Mehlmauer
69c3aab35a Update .dockerignore 2019-11-26 23:06:05 +01:00
Christian Mehlmauer
bdeb3547f1 Create rubocop.yml 2019-11-26 23:05:45 +01:00
Christian Mehlmauer
99e04b9669 Create ruby.yml 2019-11-26 23:04:03 +01:00
Christian Mehlmauer
680d2fb7eb add gem push 2019-11-26 23:03:23 +01:00
erwanlr
8814eda018 Adds DFs 2019-11-23 11:45:15 +00:00
erwanlr
7e72ba2885 Adds DFs 2019-11-16 11:18:23 +00:00
Christian Mehlmauer
b4d7a8490b change twitter handle 2019-11-13 08:23:18 +01:00
erwanlr
e9a5bc66df Bumps version 2019-11-11 12:41:29 +00:00
erwanlr
edebc77726 Fixes 1426 2019-11-09 17:55:31 +00:00
erwanlr
271dee824d Adds DFs 2019-11-09 10:59:46 +00:00
erwanlr
1e868d10ca Ignores slow specs when executing rake tasks 2019-11-05 20:11:03 +00:00
erwanlr
4be3f17ae4 Bumps version 2019-11-05 19:19:18 +00:00
erwanlr
f24e7be264 Updates dep 2019-11-05 18:47:41 +00:00
erwanlr
9adc26445d Adds DFs 2019-11-02 11:47:11 +00:00
erwanlr
353e7dcbb9 Removes ruby-head from Travis 2019-11-01 17:47:05 +00:00
erwanlr
430e65c12e Updates cms_scanner dep 2019-11-01 16:43:13 +00:00
erwanlr
1aa242a9d8 Avoids duplicates in finding the same thing diffrent pages 2019-11-01 15:20:46 +00:00
erwanlr
7173cd85fe Changes "Detected By" to "Found By" in cli output for consistency with JSON output 2019-11-01 10:52:31 +00:00
erwanlr
b95a4f55e3 Adds DFs 2019-11-01 10:32:02 +00:00
erwanlr
6b5e016770 Improves detection of WP Version, Plugins etc by checking 404 2019-11-01 09:47:44 +00:00
erwanlr
85aa9f61cd Center the banner text 2019-10-31 16:42:40 +00:00
erwanlr
5c187002d6 Updates cms_scanner dep 2019-10-31 16:27:41 +00:00
Erwan
9bc373308b Merge pull request #1420 from wpscanteam/dependabot/bundler/rubocop-tw-0.76.0
Update rubocop requirement from ~> 0.75.0 to ~> 0.76.0
2019-10-29 07:52:15 +01:00
dependabot-preview[bot]
cdeb0fc144 Update rubocop requirement from ~> 0.75.0 to ~> 0.76.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.75.0...v0.76.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-29 05:26:34 +00:00
ethicalhack3r
f1acdd9389 Remove 'no monetary cost' from LICENSE file 2019-10-28 16:42:15 +01:00
erwanlr
d6fac6a210 Adds DFs 2019-10-26 12:29:41 +01:00
Erwan
007cfb0801 Updates Ruby versions for Travis (now only latest in stable) 2019-10-26 10:58:56 +02:00
erwanlr
1f9829b7c0 Adds DFs 2019-10-19 22:56:38 +01:00
Erwan
e039d22565 Fix #1413 2019-10-17 20:31:28 +02:00
erwanlr
b0775b1610 Adds DFs 2019-10-15 17:18:40 +01:00
erwanlr
0e429700c6 Fixes #1412 2019-10-12 11:48:14 +01:00
erwanlr
af7804ca23 Adds DF 2019-10-12 10:54:21 +01:00
erwanlr
9da326967b Bumps version 2019-10-11 15:07:50 +01:00
erwanlr
62600b3a66 Fixes #1411 2019-10-11 14:32:00 +01:00
erwanlr
b236138fb5 Adds additional specs related to previous commit 2019-10-10 22:57:26 +01:00
erwanlr
40c2e9a54b Fixes non detection of plugins/themes from homepage in some cases 2019-10-10 22:33:19 +01:00
erwanlr
a9062db57f Improves detection speed of plugins/themes from homepage 2019-10-10 21:15:59 +01:00
erwanlr
2621404c5f Removes useless spec comment 2019-10-10 21:03:54 +01:00
erwanlr
c47211ca79 Fixes empty username returned in some cases 2019-10-10 20:34:39 +01:00
erwanlr
e39a192e8d Checks default wp-content dir regardless of detection mode if not found passively 2019-10-10 19:59:09 +01:00
Erwan
d85035d5ef Merge pull request #1407 from wpscanteam/dependabot/bundler/rspec-tw-3.9.0
Update rspec requirement from ~> 3.8.0 to ~> 3.9.0
2019-10-09 12:50:59 +02:00
dependabot-preview[bot]
de09a97343 Update rspec requirement from ~> 3.8.0 to ~> 3.9.0
Updates the requirements on [rspec](https://github.com/rspec/rspec) to permit the latest version.
- [Release notes](https://github.com/rspec/rspec/releases)
- [Commits](https://github.com/rspec/rspec/compare/v3.8.0...v3.9.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-09 05:48:37 +00:00
erwanlr
a6855345d7 Fixes #1406 2019-10-07 07:03:06 +01:00
erwanlr
a53f88b626 Improves WP detection 2019-10-06 16:51:35 +01:00
erwanlr
7048c82124 Adds DFs 2019-10-06 10:46:12 +01:00
erwanlr
6aa7cda478 Fixes #1404 2019-10-05 20:25:35 +01:00
erwanlr
ff339b9a8c Updates rubocop config 2019-10-03 13:09:14 +01:00
Erwan
8898cc20fe Merge pull request #1403 from wpscanteam/dependabot/bundler/rubocop-performance-tw-1.5.0
Update rubocop-performance requirement from ~> 1.4.0 to ~> 1.5.0
2019-10-02 18:35:11 +02:00
dependabot-preview[bot]
770d1da280 Update rubocop-performance requirement from ~> 1.4.0 to ~> 1.5.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.4.0...v1.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-02 06:46:49 +00:00
Erwan
6ba4e8a29b Merge pull request #1402 from wpscanteam/dependabot/bundler/rubocop-tw-0.75.0
Update rubocop requirement from ~> 0.74.0 to ~> 0.75.0
2019-10-02 08:45:36 +02:00
dependabot-preview[bot]
953ca68495 Update rubocop requirement from ~> 0.74.0 to ~> 0.75.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.74.0...v0.75.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-01 06:21:21 +00:00
Erwan
4289dfb37d Merge pull request #1401 from wpscanteam/dependabot/bundler/rake-tw-13.0
Update rake requirement from ~> 12.3 to ~> 13.0
2019-09-30 12:37:15 +02:00
dependabot-preview[bot]
4f6f2f436a Update rake requirement from ~> 12.3 to ~> 13.0
Updates the requirements on [rake](https://github.com/ruby/rake) to permit the latest version.
- [Release notes](https://github.com/ruby/rake/releases)
- [Changelog](https://github.com/ruby/rake/blob/master/History.rdoc)
- [Commits](https://github.com/ruby/rake/compare/v12.3.0...v13.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-30 05:44:30 +00:00
erwanlr
237979a479 Adds DFs 2019-09-28 17:29:35 +01:00
441 changed files with 152531 additions and 619 deletions

View File

@@ -14,3 +14,4 @@ Dockerfile
*.orig
bin/wpscan-*
.wpscan/
.github/

41
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: [2.4, 2.5, 2.6, 2.7]
steps:
- name: Checkout code
uses: actions/checkout@v1
- name: Set up Ruby ${{ matrix.ruby }}
uses: actions/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
- name: Install GEMs
run: |
gem install bundler
bundle config force_ruby_platform true
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
- name: rubocop
run: |
bundle exec rubocop
- name: rspec
run: |
bundle exec rspec
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

40
.github/workflows/gempush.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
name: Ruby Gem
on:
release:
types: [published]
jobs:
build:
name: Build + Publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Set up Ruby 2.6
uses: actions/setup-ruby@v1
with:
ruby-version: 2.6.x
#- name: Publish to GPR
# run: |
# mkdir -p $HOME/.gem
# touch $HOME/.gem/credentials
# chmod 0600 $HOME/.gem/credentials
# printf -- "---\n:github: Bearer ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
# gem build *.gemspec
# gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
# env:
# GEM_HOST_API_KEY: ${{secrets.GITHUB_TOKEN}}
# OWNER: wpscanteam
- name: Publish to RubyGems
run: |
mkdir -p $HOME/.gem
touch $HOME/.gem/credentials
chmod 0600 $HOME/.gem/credentials
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
gem build *.gemspec
gem push *.gem
env:
GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}

5
.rspec
View File

@@ -1,3 +1,2 @@
--color
--fail-fast
--require spec_helper
--require spec_helper
--color

View File

@@ -4,16 +4,10 @@ AllCops:
Exclude:
- '*.gemspec'
- 'vendor/**/*'
ClassVars:
Enabled: false
LineLength:
Layout/LineLength:
Max: 120
Lint/UriEscapeUnescape:
Enabled: false
MethodLength:
Max: 20
Exclude:
- 'app/controllers/enumeration/cli_options.rb'
Metrics/AbcSize:
Max: 25
Metrics/BlockLength:
@@ -25,6 +19,12 @@ Metrics/ClassLength:
- 'app/controllers/enumeration/cli_options.rb'
Metrics/CyclomaticComplexity:
Max: 8
Metrics/MethodLength:
Max: 20
Exclude:
- 'app/controllers/enumeration/cli_options.rb'
Style/ClassVars:
Enabled: false
Style/Documentation:
Enabled: false
Style/FormatStringToken:

View File

@@ -1,4 +1,18 @@
if ENV['GITHUB_ACTION']
require 'simplecov-lcov'
SimpleCov::Formatter::LcovFormatter.config do |c|
c.single_report_path = 'coverage/lcov.info'
c.report_with_single_file = true
end
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
end
SimpleCov.start do
enable_coverage :branch # Only supported for Ruby >= 2.5
add_filter '/spec/'
add_filter 'helper'
end

View File

@@ -1,33 +0,0 @@
language: ruby
sudo: false
cache: bundler
rvm:
- 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
- 2.5.3
- 2.5.4
- 2.5.5
- 2.6.0
- 2.6.1
- 2.6.2
- 2.6.3
- ruby-head
before_install:
- "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
- gem update --system
matrix:
allow_failures:
- rvm: ruby-head
script:
- bundle exec rubocop
- bundle exec rspec
notifications:
email:
- team@wpscan.org

View File

@@ -38,4 +38,3 @@ USER wpscan
RUN /usr/local/bundle/bin/wpscan --update --verbose
ENTRYPOINT ["/usr/local/bundle/bin/wpscan"]
CMD ["--help"]

View File

@@ -29,8 +29,6 @@ Example cases which do not require a commercial license, and thus fall under the
If you need to purchase a commercial license or are unsure whether you need to purchase a commercial license contact us - team@wpscan.org.
We may grant commercial licenses at no monetary cost at our own discretion if the commercial usage is deemed by the WPScan Team to significantly benefit WPScan.
Free-use Terms and Conditions;
3. Redistribution

View File

@@ -15,7 +15,7 @@
<p align="center">
<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://github.com/wpscanteam/wpscan/actions?query=workflow%3ABuild" target="_blank"><img src="https://github.com/wpscanteam/wpscan/workflows/Build/badge.svg"></a>
<a href="https://codeclimate.com/github/wpscanteam/wpscan" target="_blank"><img src="https://codeclimate.com/github/wpscanteam/wpscan/badges/gpa.svg"></a>
</p>
@@ -130,6 +130,11 @@ cli_options:
api_token: YOUR_API_TOKEN
```
## Load API Token From ENV (since v3.7.10)
The API Token will be automatically loaded from the ENV variable `WPSCAN_API_TOKEN` if present. If the `--api-token` CLI option is also provided, the value from the CLI will be used.
## Enumerating usernames
```shell

View File

@@ -6,14 +6,18 @@ exec = []
begin
require 'rubocop/rake_task'
RuboCop::RakeTask.new
exec << :rubocop
rescue LoadError
end
begin
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
RSpec::Core::RakeTask.new(:spec) { |t| t.rspec_opts = %w{--tag ~slow} }
exec << :spec
rescue LoadError
end

View File

@@ -18,9 +18,7 @@ module WPScan
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(ParsedCli.detection_mode)
raise Error::WpContentDirNotDetected
raise Error::WpContentDirNotDetected unless target.content_dir
end
end
end

View File

@@ -4,6 +4,8 @@ module WPScan
module Controller
# Controller to handle the API token
class VulnApi < CMSScanner::Controller::Base
ENV_KEY = 'WPSCAN_API_TOKEN'
def cli_options
[
OptString.new(['--api-token TOKEN', 'The WPVulnDB API Token to display vulnerability data'])
@@ -11,9 +13,9 @@ module WPScan
end
def before_scan
return unless ParsedCli.api_token
return unless ParsedCli.api_token || ENV.key?(ENV_KEY)
DB::VulnApi.token = ParsedCli.api_token
DB::VulnApi.token = ParsedCli.api_token || ENV[ENV_KEY]
api_status = DB::VulnApi.status

View File

@@ -4,7 +4,6 @@ module WPScan
module Finders
module DbExports
# DB Exports finder
# See https://github.com/wpscanteam/wpscan-v3/issues/62
class KnownLocations < CMSScanner::Finders::Finder
include CMSScanner::Finders::Finder::Enumerator
@@ -41,7 +40,7 @@ module WPScan
# @return [ Hash ]
def potential_urls(opts = {})
urls = {}
domain_name = target.uri.host[/(^[\w|-]+)/, 1]
domain_name = PublicSuffix.domain(target.uri.host)[/(^[\w|-]+)/, 1]
File.open(opts[:list]).each_with_index do |path, index|
path.gsub!('{domain_name}', domain_name)

View File

@@ -16,8 +16,7 @@ module WPScan
target.url(path),
confidence: 70,
found_by: DIRECT_ACCESS,
interesting_entries: target.directory_listing_entries(path),
references: { url: 'https://github.com/wpscanteam/wpscan/issues/422' }
interesting_entries: target.directory_listing_entries(path)
)
end
end

View File

@@ -11,11 +11,7 @@ module WPScan
return unless target.debug_log?(path)
Model::DebugLog.new(
target.url(path),
confidence: 100, found_by: DIRECT_ACCESS,
references: { url: 'https://codex.wordpress.org/Debugging_in_WordPress' }
)
Model::DebugLog.new(target.url(path), confidence: 100, found_by: DIRECT_ACCESS)
end
end
end

View File

@@ -11,12 +11,7 @@ module WPScan
return unless /DUPLICATOR INSTALL-LOG/.match?(target.head_and_get(path).body)
Model::DuplicatorInstallerLog.new(
target.url(path),
confidence: 100,
found_by: DIRECT_ACCESS,
references: { url: 'https://www.exploit-db.com/ghdb/3981/' }
)
Model::DuplicatorInstallerLog.new(target.url(path), confidence: 100, found_by: DIRECT_ACCESS)
end
end
end

View File

@@ -15,10 +15,7 @@ module WPScan
Model::EmergencyPwdResetScript.new(
target.url(path),
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'
}
found_by: DIRECT_ACCESS
)
end
end

View File

@@ -16,8 +16,7 @@ module WPScan
target.url(path),
confidence: 100,
found_by: DIRECT_ACCESS,
interesting_entries: fpd_entries,
references: { url: 'https://www.owasp.org/index.php/Full_Path_Disclosure' }
interesting_entries: fpd_entries
)
end
end

View File

@@ -9,20 +9,14 @@ module WPScan
def passive(_opts = {})
pattern = %r{#{target.content_dir}/mu\-plugins/}i
target.in_scope_uris(target.homepage_res) do |uri|
target.in_scope_uris(target.homepage_res, '(//@href|//@src)[contains(., "mu-plugins")]') do |uri|
next unless uri.path&.match?(pattern)
url = target.url('wp-content/mu-plugins/')
target.mu_plugins = true
return Model::MuPlugins.new(
url,
confidence: 70,
found_by: 'URLs In Homepage (Passive Detection)',
to_s: "This site has 'Must Use Plugins': #{url}",
references: { url: 'http://codex.wordpress.org/Must_Use_Plugins' }
)
return Model::MuPlugins.new(url, confidence: 70, found_by: 'URLs In Homepage (Passive Detection)')
end
nil
end
@@ -37,13 +31,7 @@ module WPScan
target.mu_plugins = true
Model::MuPlugins.new(
url,
confidence: 80,
found_by: DIRECT_ACCESS,
to_s: "This site has 'Must Use Plugins': #{url}",
references: { url: 'http://codex.wordpress.org/Must_Use_Plugins' }
)
Model::MuPlugins.new(url, confidence: 80, found_by: DIRECT_ACCESS)
end
end
end

View File

@@ -17,13 +17,7 @@ module WPScan
target.multisite = true
Model::Multisite.new(
url,
confidence: 100,
found_by: DIRECT_ACCESS,
to_s: 'This site seems to be a multisite',
references: { url: 'http://codex.wordpress.org/Glossary#Multisite' }
)
Model::Multisite.new(url, confidence: 100, found_by: DIRECT_ACCESS)
end
end
end

View File

@@ -20,12 +20,7 @@ module WPScan
target.registration_enabled = true
Model::Registration.new(
res.effective_url,
confidence: 100,
found_by: DIRECT_ACCESS,
to_s: "Registration is enabled: #{res.effective_url}"
)
Model::Registration.new(res.effective_url, confidence: 100, found_by: DIRECT_ACCESS)
end
end
end

View File

@@ -13,12 +13,7 @@ module WPScan
return unless res.code == 200 && res.headers['Content-Type'] =~ %r{\Aapplication/zip}i
Model::TmmDbMigrate.new(
url,
confidence: 100,
found_by: DIRECT_ACCESS,
references: { packetstorm: 131_957 }
)
Model::TmmDbMigrate.new(url, confidence: 100, found_by: DIRECT_ACCESS)
end
end
end

View File

@@ -13,12 +13,7 @@ module WPScan
url = target.url(path)
Model::UploadDirectoryListing.new(
url,
confidence: 100,
found_by: DIRECT_ACCESS,
to_s: "Upload directory has listing enabled: #{url}"
)
Model::UploadDirectoryListing.new(url, confidence: 100, found_by: DIRECT_ACCESS)
end
end
end

View File

@@ -14,11 +14,7 @@ module WPScan
return unless SQL_PATTERN.match?(res.body)
Model::UploadSQLDump.new(
target.url(path),
confidence: 100,
found_by: DIRECT_ACCESS
)
Model::UploadSQLDump.new(target.url(path), confidence: 100, found_by: DIRECT_ACCESS)
end
end
end

View File

@@ -11,17 +11,7 @@ module WPScan
return unless res.code == 200
Model::WPCron.new(
wp_cron_url,
confidence: 60,
found_by: DIRECT_ACCESS,
references: {
url: [
'https://www.iplocation.net/defend-wordpress-from-ddos',
'https://github.com/wpscanteam/wpscan/issues/1299'
]
}
)
Model::WPCron.new(wp_cron_url, confidence: 60, found_by: DIRECT_ACCESS)
end
def wp_cron_url

View File

@@ -1,8 +1,10 @@
# frozen_string_literal: true
require_relative 'main_theme/css_style'
require_relative 'main_theme/css_style_in_homepage'
require_relative 'main_theme/css_style_in_404_page'
require_relative 'main_theme/woo_framework_meta_generator'
require_relative 'main_theme/urls_in_homepage'
require_relative 'main_theme/urls_in_404_page'
module WPScan
module Finders
@@ -14,9 +16,11 @@ module WPScan
# @param [ WPScan::Target ] target
def initialize(target)
finders <<
MainTheme::CssStyle.new(target) <<
MainTheme::CssStyleInHomepage.new(target) <<
MainTheme::CssStyleIn404Page.new(target) <<
MainTheme::WooFrameworkMetaGenerator.new(target) <<
MainTheme::UrlsInHomepage.new(target)
MainTheme::UrlsInHomepage.new(target) <<
MainTheme::UrlsIn404Page.new(target)
end
end
end

View File

@@ -0,0 +1,14 @@
# frozen_string_literal: true
module WPScan
module Finders
module MainTheme
# From the CSS style in the 404 page
class CssStyleIn404Page < CssStyleInHomepage
def passive(opts = {})
passive_from_css_href(target.error_404_res, opts) || passive_from_style_code(target.error_404_res, opts)
end
end
end
end
end

View File

@@ -3,9 +3,9 @@
module WPScan
module Finders
module MainTheme
# From the css style
class CssStyle < CMSScanner::Finders::Finder
include Finders::WpItems::URLsInHomepage
# From the CSS style in the homepage
class CssStyleInHomepage < CMSScanner::Finders::Finder
include Finders::WpItems::UrlsInPage # To have the item_code_pattern method available here
def create_theme(slug, style_url, opts)
Model::Theme.new(
@@ -20,7 +20,7 @@ module WPScan
end
def passive_from_css_href(res, opts)
target.in_scope_uris(res, '//style/@src|//link/@href') do |uri|
target.in_scope_uris(res, '//link/@href[contains(., "style.css")]') do |uri|
next unless uri.path =~ %r{/themes/([^\/]+)/style.css\z}i
return create_theme(Regexp.last_match[1], uri.to_s, opts)

View File

@@ -0,0 +1,15 @@
# frozen_string_literal: true
module WPScan
module Finders
module MainTheme
# URLs In 404 Page Finder
class UrlsIn404Page < UrlsInHomepage
# @return [ Typhoeus::Response ]
def page_res
@page_res ||= target.error_404_res
end
end
end
end
end

View File

@@ -5,7 +5,7 @@ module WPScan
module MainTheme
# URLs In Homepage Finder
class UrlsInHomepage < CMSScanner::Finders::Finder
include WpItems::URLsInHomepage
include WpItems::UrlsInPage
# @param [ Hash ] opts
#
@@ -21,6 +21,11 @@ module WPScan
found
end
# @return [ Typhoeus::Response ]
def page_res
@page_res ||= target.homepage_res
end
end
end
end

View File

@@ -10,7 +10,7 @@ module WPScan
PATTERN = /#{THEME_PATTERN}\s+#{FRAMEWORK_PATTERN}/i.freeze
def passive(opts = {})
return unless target.homepage_res.body =~ PATTERN
return unless target.homepage_res.body =~ PATTERN || target.error_404_res.body =~ PATTERN
Model::Theme.new(
Regexp.last_match[1],

View File

@@ -16,7 +16,7 @@ module WPScan
end
def errored_response?(response)
response.code != 200 && response.body !~ /login_error/i
response.code != 200 && response.body !~ /Incorrect username or password/i
end
end
end

View File

@@ -1,6 +1,7 @@
# frozen_string_literal: true
require_relative 'plugins/urls_in_homepage'
require_relative 'plugins/urls_in_404_page'
require_relative 'plugins/known_locations'
# From the DynamicFinders
require_relative 'plugins/comment'
@@ -22,6 +23,7 @@ module WPScan
def initialize(target)
finders <<
Plugins::UrlsInHomepage.new(target) <<
Plugins::UrlsIn404Page.new(target) <<
Plugins::HeaderPattern.new(target) <<
Plugins::Comment.new(target) <<
Plugins::Xpath.new(target) <<

View File

@@ -19,8 +19,12 @@ module WPScan
def aggressive(opts = {})
found = []
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))
enumerate(target_urls(opts), opts.merge(check_full_response: true)) do |res, slug|
finding_opts = opts.merge(found_by: found_by,
confidence: 80,
interesting_entries: ["#{res.effective_url}, status: #{res.code}"])
found << Model::Plugin.new(slug, target, finding_opts)
raise Error::PluginsThresholdReached if opts[:threshold].positive? && found.size >= opts[:threshold]
end

View File

@@ -0,0 +1,16 @@
# frozen_string_literal: true
module WPScan
module Finders
module Plugins
# URLs In 404 Page Finder
# Typically, the items detected from URLs like /wp-content/plugins/<slug>/
class UrlsIn404Page < UrlsInHomepage
# @return [ Typhoeus::Response ]
def page_res
@page_res ||= target.error_404_res
end
end
end
end
end

View File

@@ -4,10 +4,9 @@ module WPScan
module Finders
module Plugins
# URLs In Homepage Finder
# Typically, the items detected from URLs like
# /wp-content/plugins/<slug>/
# Typically, the items detected from URLs like /wp-content/plugins/<slug>/
class UrlsInHomepage < CMSScanner::Finders::Finder
include WpItems::URLsInHomepage
include WpItems::UrlsInPage
# @param [ Hash ] opts
#
@@ -21,6 +20,11 @@ module WPScan
found
end
# @return [ Typhoeus::Response ]
def page_res
@page_res ||= target.homepage_res
end
end
end
end

View File

@@ -1,12 +1,13 @@
# frozen_string_literal: true
require_relative 'themes/urls_in_homepage'
require_relative 'themes/urls_in_404_page'
require_relative 'themes/known_locations'
module WPScan
module Finders
module Themes
# themes Finder
# Themes Finder
class Base
include CMSScanner::Finders::SameTypeFinder
@@ -14,6 +15,7 @@ module WPScan
def initialize(target)
finders <<
Themes::UrlsInHomepage.new(target) <<
Themes::UrlsIn404Page.new(target) <<
Themes::KnownLocations.new(target)
end
end

View File

@@ -19,8 +19,12 @@ module WPScan
def aggressive(opts = {})
found = []
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))
enumerate(target_urls(opts), opts.merge(check_full_response: true)) do |res, slug|
finding_opts = opts.merge(found_by: found_by,
confidence: 80,
interesting_entries: ["#{res.effective_url}, status: #{res.code}"])
found << Model::Theme.new(slug, target, finding_opts)
raise Error::ThemesThresholdReached if opts[:threshold].positive? && found.size >= opts[:threshold]
end

View File

@@ -0,0 +1,15 @@
# frozen_string_literal: true
module WPScan
module Finders
module Themes
# URLs In 04 Page Finder
class UrlsIn404Page < UrlsInHomepage
# @return [ Typhoeus::Response ]
def page_res
@page_res ||= target.error_404_res
end
end
end
end
end

View File

@@ -5,7 +5,7 @@ module WPScan
module Themes
# URLs In Homepage Finder
class UrlsInHomepage < CMSScanner::Finders::Finder
include WpItems::URLsInHomepage
include WpItems::UrlsInPage
# @param [ Hash ] opts
#
@@ -19,6 +19,11 @@ module WPScan
found
end
# @return [ Typhoeus::Response ]
def page_res
@page_res ||= target.homepage_res
end
end
end
end

View File

@@ -71,11 +71,13 @@ module WPScan
return username, 'Display Name', 50 if username
end
# @param [ String ] url
# @param [ String, Addressable::URI ] uri
#
# @return [ String, nil ]
def username_from_author_url(url)
url[%r{/author/([^/\b]+)/?}i, 1]
def username_from_author_url(uri)
uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI)
uri.path[%r{/author/([^/\b]+)/?}i, 1]
end
# @param [ Typhoeus::Response ] res
@@ -83,12 +85,12 @@ module WPScan
# @return [ String, nil ] The username found
def username_from_response(res)
# Permalink enabled
target.in_scope_uris(res, '//link/@href|//a/@href') do |uri|
username = username_from_author_url(uri.to_s)
target.in_scope_uris(res, '//@href[contains(., "author/")]') do |uri|
username = username_from_author_url(uri)
return username if username
end
# No permalink
# No permalink, TODO Maybe use xpath to extract the classes ?
res.body[/<body class="archive author author-([^\s]+)[ "]/i, 1]
end
@@ -97,9 +99,12 @@ module WPScan
# @return [ String, nil ]
def display_name_from_body(body)
page = Nokogiri::HTML.parse(body)
# WP >= 3.0
page.css('h1.page-title span').each do |node|
return node.text.to_s
text = node.text.to_s.strip
return text unless text.empty?
end
# WP < 3.0

View File

@@ -45,7 +45,7 @@ module WPScan
def potential_usernames(res)
usernames = []
target.in_scope_uris(res, '//a/@href') do |uri, node|
target.in_scope_uris(res, '//a/@href[contains(., "author")]') do |uri, node|
if uri.path =~ %r{/author/([^/\b]+)/?\z}i
usernames << [Regexp.last_match[1], 'Author Pattern', 100]
elsif /author=[0-9]+/.match?(uri.query)

View File

@@ -34,6 +34,8 @@ module WPScan
def user_details_from_oembed_data(oembed_data)
return unless oembed_data
oembed_data = oembed_data.first if oembed_data.is_a?(Array)
if oembed_data['author_url'] =~ %r{/author/([^/]+)/?\z}
details = [Regexp.last_match[1], 'Author URL', 90]
elsif oembed_data['author_name'] && !oembed_data['author_name'].empty?

View File

@@ -21,7 +21,7 @@ module WPScan
loop do
current_page += 1
res = Typhoeus.get(api_url, params: { per_page: MAX_PER_PAGE, page: current_page })
res = Browser.get(api_url, params: { per_page: MAX_PER_PAGE, page: current_page })
total_pages ||= res.headers['X-WP-TotalPages'].to_i

View File

@@ -1,3 +1,3 @@
# frozen_string_literal: true
require_relative 'wp_items/urls_in_homepage'
require_relative 'wp_items/urls_in_page'

View File

@@ -4,18 +4,24 @@ module WPScan
module Finders
module WpItems
# URLs In Homepage Module to use in plugins & themes finders
module URLsInHomepage
module UrlsInPage
# @param [ String ] type plugins / themes
# @param [ Boolean ] uniq Wether or not to apply the #uniq on the results
#
# @return [Array<String> ] The plugins/themes detected in the href, src attributes of the homepage
# @return [ Array<String> ] The plugins/themes detected in the href, src attributes of the page
def items_from_links(type, uniq = true)
found = []
xpath = format(
'(//@href|//@src|//@data-src)[contains(., "%s")]',
type == 'plugins' ? target.plugins_dir : target.content_dir
)
target.in_scope_uris(target.homepage_res) do |uri|
target.in_scope_uris(page_res, xpath) do |uri|
next unless uri.to_s =~ item_attribute_pattern(type)
found << Regexp.last_match[1]
slug = Regexp.last_match[1]&.strip
found << slug unless slug&.empty?
end
uniq ? found.uniq.sort : found.sort
@@ -28,7 +34,7 @@ module WPScan
def items_from_codes(type, uniq = true)
found = []
target.homepage_res.html.css('script,style').each do |tag|
page_res.html.xpath('//script[not(@src)]|//style[not(@src)]').each do |tag|
code = tag.text.to_s
next if code.empty?
@@ -42,7 +48,7 @@ module WPScan
#
# @return [ Regexp ]
def item_attribute_pattern(type)
@item_attribute_pattern ||= %r{\A#{item_url_pattern(type)}([^/]+)/}i
@item_attribute_pattern ||= %r{#{item_url_pattern(type)}([^/]+)/}i
end
# @param [ String ] type
@@ -59,7 +65,7 @@ module WPScan
item_dir = type == 'plugins' ? target.plugins_dir : target.content_dir
item_url = type == 'plugins' ? target.plugins_url : target.content_url
url = /#{item_url.gsub(/\A(?:http|https)/i, 'https?').gsub('/', '\\\\\?\/')}/i
url = /#{item_url.gsub(/\A(?:https?)/i, 'https?').gsub('/', '\\\\\?\/')}/i
item_dir = %r{(?:#{url}|\\?\/#{item_dir.gsub('/', '\\\\\?\/')}\\?/)}i
type == 'plugins' ? item_dir : %r{#{item_dir}#{type}\\?\/}i

View File

@@ -28,7 +28,7 @@ module WPScan
end
def passive_urls_xpath
'//a[contains(@href, "rdf")]/@href'
'//a[contains(@href, "/rdf")]/@href'
end
def aggressive_urls(_opts = {})

View File

@@ -8,45 +8,110 @@ module WPScan
end
#
# Empty classes for the #type to be correctly displayed (as taken from the self.class from the parent)
# Some classes are empty for the #type to be correctly displayed (as taken from the self.class from the parent)
#
class BackupDB < InterestingFinding
# @return [ Hash ]
def references
@references ||= { url: ['https://github.com/wpscanteam/wpscan/issues/422'] }
end
end
class DebugLog < InterestingFinding
# @ return [ Hash ]
def references
@references ||= { url: ['https://codex.wordpress.org/Debugging_in_WordPress'] }
end
end
class DuplicatorInstallerLog < InterestingFinding
# @return [ Hash ]
def references
@references ||= { url: ['https://www.exploit-db.com/ghdb/3981/'] }
end
end
class EmergencyPwdResetScript < InterestingFinding
def references
@references ||= {
url: ['https://codex.wordpress.org/Resetting_Your_Password#Using_the_Emergency_Password_Reset_Script']
}
end
end
class FullPathDisclosure < InterestingFinding
# @return [ Hash ]
def references
@references ||= { url: ['https://www.owasp.org/index.php/Full_Path_Disclosure'] }
end
end
class MuPlugins < InterestingFinding
# @return [ String ]
def to_s
@to_s ||= "This site has 'Must Use Plugins': #{url}"
end
# @return [ Hash ]
def references
@references ||= { url: ['http://codex.wordpress.org/Must_Use_Plugins'] }
end
end
class Multisite < InterestingFinding
# @return [ String ]
def to_s
@to_s ||= 'This site seems to be a multisite'
end
# @return [ Hash ]
def references
@references ||= { url: ['http://codex.wordpress.org/Glossary#Multisite'] }
end
end
class Readme < InterestingFinding
end
class Registration < InterestingFinding
# @return [ String ]
def to_s
@to_s ||= "Registration is enabled: #{url}"
end
end
class TmmDbMigrate < InterestingFinding
# @return [ Hash ]
def references
@references ||= { packetstorm: [131_957] }
end
end
class UploadDirectoryListing < InterestingFinding
# @return [ String ]
def to_s
@to_s ||= "Upload directory has listing enabled: #{url}"
end
end
class UploadSQLDump < InterestingFinding
end
class WPCron < InterestingFinding
# @return [ String ]
def to_s
@to_s ||= "The external WP-Cron seems to be enabled: #{url}"
end
# @return [ Hash ]
def references
@references ||= {
url: [
'https://www.iplocation.net/defend-wordpress-from-ddos',
'https://github.com/wpscanteam/wpscan/issues/1299'
]
}
end
end
end
end

View File

@@ -101,7 +101,7 @@ module WPScan
#
# @return [ String ]
def parse_style_tag(body, tag)
value = body[/^\s*#{Regexp.escape(tag)}:[\t ]*([^\r\n]+)/i, 1]
value = body[/#{Regexp.escape(tag)}:[\t ]*([^\r\n\*]+)/i, 1]
value && !value.strip.empty? ? value.strip : nil
end

View File

@@ -14,7 +14,7 @@ module WPScan
attr_reader :uri, :slug, :detection_opts, :version_detection_opts, :blog, :path_from_blog, :db_data
delegate :homepage_res, :xpath_pattern_from_page, :in_scope_uris, :head_or_get_params, to: :blog
delegate :homepage_res, :error_404_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
@@ -23,7 +23,7 @@ module WPScan
# @option opts [ Hash ] :version_detection The options to use when looking for the version
# @option opts [ String ] :url The URL of the item
def initialize(slug, blog, opts = {})
@slug = URI.decode(slug)
@slug = Addressable::URI.unencode(slug)
@blog = blog
@uri = Addressable::URI.parse(opts[:url]) if opts[:url]
@@ -83,11 +83,6 @@ module WPScan
end
end
# URI.encode is preferered over Addressable::URI.encode as it will encode
# leading # character:
# URI.encode('#t#') => %23t%23
# Addressable::URI.encode('#t#') => #t%23
#
# @param [ String ] path Optional path to merge with the uri
#
# @return [ String ]
@@ -95,7 +90,7 @@ module WPScan
return unless @uri
return @uri.to_s unless path
@uri.join(URI.encode(path)).to_s
@uri.join(Addressable::URI.encode(path)).to_s
end
# @return [ Boolean ]
@@ -166,7 +161,7 @@ module WPScan
# @return [ Typhoeus::Response ]
def head_and_get(path, codes = [200], params = {})
final_path = +@path_from_blog
final_path << URI.encode(path) unless path.nil?
final_path << path unless path.nil?
blog.head_and_get(final_path, codes, params)
end

View File

@@ -8,7 +8,7 @@ module WPScan
# @return [ Hash ]
def references
{
@references ||= {
url: ['http://codex.wordpress.org/XML-RPC_Pingback_API'],
metasploit: [
'auxiliary/scanner/http/wordpress_ghost_scanner',

View File

@@ -1,14 +1,14 @@
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version <%= WPScan::VERSION %>
WordPress Security Scanner by the WPScan Team
Version <%= WPScan::VERSION %>
<%= ' ' * ((63 - WPScan::DB::Sponsor.text.length)/2) + WPScan::DB::Sponsor.text %>
@_WPScan_, @ethicalhack3r, @erwan_lr, @_FireFart_
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________

View File

@@ -1,4 +1,4 @@
| Detected By: <%= @item.found_by %>
| Found By: <%= @item.found_by %>
<% @item.interesting_entries.each do |entry| -%>
| - <%= entry %>
<% end -%>

View File

@@ -9,5 +9,5 @@
<% end -%>
<% else -%>
<%= warning_icon %> No WPVulnDB API Token given, as a result vulnerability data has not been output.
<%= warning_icon %> You can get a free API token with 50 daily requests by registering at https://wpvulndb.com/users/sign_up.
<%= warning_icon %> You can get a free API token with 50 daily requests by registering at https://wpvulndb.com/users/sign_up
<% end -%>

View File

@@ -5,7 +5,7 @@
"@_WPScan_",
"@ethicalhack3r",
"@erwan_lr",
"@_FireFart_"
"@firefart"
],
"sponsor": <%= WPScan::DB::Sponsor.text.to_json %>
},

View File

@@ -8,6 +8,6 @@
"requests_remaining": <%= @status['requests_remaining'].to_json %>
<% end -%>
<% else -%>
"error": "No WPVulnDB API Token given, as a result vulnerability data has not been output.\nYou can get a free API token with 50 daily requests by registering at https://wpvulndb.com/users/sign_up."
"error": "No WPVulnDB API Token given, as a result vulnerability data has not been output.\nYou can get a free API token with 50 daily requests by registering at https://wpvulndb.com/users/sign_up"
<% end -%>
},

View File

@@ -67,13 +67,13 @@ module WPScan
# @return [ Hash ] The params for Typhoeus::Request
# @note Those params can't be overriden by CLI options
def request_params
@request_params ||= {
@request_params ||= Browser.instance.default_connect_request_params.merge(
timeout: 600,
connecttimeout: 300,
accept_encoding: 'gzip, deflate',
cache_ttl: 0,
headers: { 'User-Agent' => Browser.instance.default_user_agent, 'Referer' => nil }
}
headers: { 'User-Agent' => Browser.instance.default_user_agent }
)
end
# @return [ String ] The raw file URL associated with the given filename
@@ -85,7 +85,7 @@ module WPScan
def remote_file_checksum(filename)
url = "#{remote_file_url(filename)}.sha512"
res = Browser.get(url, request_params)
res = Typhoeus.get(url, request_params)
raise Error::Download, res if res.timed_out? || res.code != 200
res.body.chomp
@@ -126,7 +126,7 @@ module WPScan
file_path = local_file_path(filename)
file_url = remote_file_url(filename)
res = Browser.get(file_url, request_params)
res = Typhoeus.get(file_url, request_params)
raise Error::Download, res if res.timed_out? || res.code != 200
File.open(file_path, 'wb') { |f| f.write(res.body) }
@@ -148,7 +148,7 @@ module WPScan
create_backup(filename)
dl_checksum = download(filename)
raise "#{filename}: checksums do not match" unless dl_checksum == db_checksum
raise Error::ChecksumsMismatch, filename unless dl_checksum == db_checksum
updated << filename
rescue StandardError => e

View File

@@ -21,8 +21,10 @@ module WPScan
# @return [ Hash ]
def self.get(path, params = {})
return {} unless token
return {} if path.end_with?('/latest') # Remove this when api/v4 is up
res = Browser.get(uri.join(path), params.merge(request_params))
# Typhoeus.get is used rather than Browser.get to avoid merging irrelevant params from the CLI
res = Typhoeus.get(uri.join(path), default_request_params.merge(params))
return {} if res.code == 404 # This is for API inconsistencies when dots in path
return JSON.parse(res.body) if NON_ERROR_CODES.include?(res.code)
@@ -64,15 +66,14 @@ module WPScan
end
# @return [ Hash ]
def self.request_params
{
# @note Those params can not be overriden by CLI options
def self.default_request_params
Browser.instance.default_connect_request_params.merge(
headers: {
'Host' => uri.host, # Reset in case user provided a --vhost for the target
'Referer' => nil, # Removes referer set by the cmsscanner to the target url
'User-Agent' => Browser.instance.default_user_agent,
'Authorization' => "Token token=#{token}"
}
}
)
end
end
end

View File

@@ -8,5 +8,17 @@ module WPScan
'Update required, you can not run a scan if a database file is missing.'
end
end
class ChecksumsMismatch < Standard
attr_reader :db_file
def initialize(db_file)
@db_file = db_file
end
def to_s
"#{db_file}: checksums do not match. Please try again in a few minutes."
end
end
end
end

View File

@@ -44,19 +44,27 @@ module WPScan
#
# @param [ Typhoeus::Response ] response
# @param [ Hash ] opts
# @return [ Mixed ]
# @return [ Mixed: nil, Object, Array ]
def find(_response, _opts = {})
raise NoMethodError
end
# @param [ Hash ] opts
# @return [ Mixed ] See #find
def passive(opts = {})
return if self.class::PATH
find(target.homepage_res, opts)
homepage_result = find(target.homepage_res, opts)
if homepage_result
return homepage_result unless homepage_result.is_a?(Array) && homepage_result.empty?
end
find(target.error_404_res, opts)
end
# @param [ Hash ] opts
# @return [ Mixed ] See #find
def aggressive(opts = {})
return unless self.class::PATH

View File

@@ -31,9 +31,14 @@ module WPScan
passive_configs.each do |slug, configs|
configs.each do |klass, config|
item = process_response(opts, target.homepage_res, slug, klass, config)
[target.homepage_res, target.error_404_res].each do |page_res|
item = process_response(opts, page_res, slug, klass, config)
found << item if item.is_a?(Model::WpItem)
if item.is_a?(Model::WpItem)
found << item
break # No need to check the other page if detected in the current
end
end
end
end

View File

@@ -37,6 +37,8 @@ module WPScan
end
end
# This one has been disabled from the DF.yml as it was causing FPs when a plugin had numerous
# files matching a known WP version.
class WpItemQueryParameter < QueryParameter
def xpath
@xpath ||=

View File

@@ -11,7 +11,9 @@ module WPScan
module WordPress
include CMSScanner::Target::Platform::PHP
WORDPRESS_PATTERN = %r{/(?:(?:wp-content/(?:themes|(?:mu\-)?plugins|uploads))|wp-includes)/}i.freeze
WORDPRESS_PATTERN = %r{/(?:(?:wp-content/(?:themes|(?:mu\-)?plugins|uploads))|wp-includes)/}i.freeze
WP_JSON_OEMBED_PATTERN = %r{/wp\-json/oembed/}i.freeze
WP_ADMIN_AJAX_PATTERN = %r{\\?/wp\-admin\\?/admin\-ajax\.php}i.freeze
# These methods are used in the associated interesting_findings finders
# to keep the boolean state of the finding rather than re-check the whole thing again
@@ -22,22 +24,20 @@ module WPScan
# @param [ Symbol ] detection_mode
#
# @return [ Boolean ]
# @return [ Boolean ] Whether or not the target is running WordPress
def wordpress?(detection_mode)
in_scope_uris(homepage_res) do |uri|
return true if uri.path.match(WORDPRESS_PATTERN)
[homepage_res, error_404_res].each do |page_res|
return true if wordpress_from_meta_comments_or_scripts?(page_res)
end
homepage_res.html.css('meta[name="generator"]').each do |node|
return true if /wordpress/i.match?(node['content'])
end
return true unless comments_from_page(/wordpress/i, homepage_res).empty?
if %i[mixed aggressive].include?(detection_mode)
%w[wp-admin/install.php wp-login.php].each do |path|
in_scope_uris(Browser.get_and_follow_location(url(path))).each do |uri|
return true if uri.path.match(WORDPRESS_PATTERN)
res = Browser.get_and_follow_location(url(path))
next unless res.code == 200
in_scope_uris(res, '//link/@href|//script/@src') do |uri|
return true if WORDPRESS_PATTERN.match?(uri.path)
end
end
end
@@ -45,6 +45,26 @@ module WPScan
false
end
# @param [ Typhoeus::Response ] response
# @return [ Boolean ]
def wordpress_from_meta_comments_or_scripts?(response)
in_scope_uris(response, '//link/@href|//script/@src') do |uri|
return true if WORDPRESS_PATTERN.match?(uri.path) || WP_JSON_OEMBED_PATTERN.match?(uri.path)
end
return true if response.html.css('meta[name="generator"]').any? do |node|
/wordpress/i.match?(node['content'])
end
return true unless comments_from_page(/wordpress/i, response).empty?
return true if response.html.xpath('//script[not(@src)]').any? do |node|
WP_ADMIN_AJAX_PATTERN.match?(node.text)
end
false
end
COOKIE_PATTERNS = {
'vjs' => /createCookie\('vjs','(?<c_value>\d+)',\d+\);/i
}.freeze
@@ -82,10 +102,11 @@ module WPScan
def wordpress_hosted?
return true if /\.wordpress\.com$/i.match?(uri.host)
unless content_dir(:passive)
unless content_dir
pattern = %r{https?://s\d\.wp\.com#{WORDPRESS_PATTERN}}i.freeze
xpath = '(//@href|//@src)[contains(., "wp.com")]'
uris_from_page(homepage_res) do |uri|
uris_from_page(homepage_res, xpath) do |uri|
return true if uri.to_s.match?(pattern)
end
end

View File

@@ -13,25 +13,24 @@ module WPScan
@plugins_dir = dir.chomp('/')
end
# @param [ Symbol ] detection_mode
# @return [ String ] The wp-content directory
def content_dir(detection_mode = :mixed)
def content_dir
unless @content_dir
# scope_url_pattern is from CMSScanner::Target
pattern = %r{#{scope_url_pattern}([\w\s\-/]+)\\?/(?:themes|plugins|uploads|cache)\\?/}i
pattern = %r{#{scope_url_pattern}([\w\s\-/]+?)\\?/(?:themes|plugins|uploads|cache)\\?/}i
in_scope_uris(homepage_res) do |uri|
return @content_dir = Regexp.last_match[1] if uri.to_s.match(pattern)
[homepage_res, error_404_res].each do |page_res|
in_scope_uris(page_res, '//link/@href|//script/@src|//img/@src') do |uri|
return @content_dir = Regexp.last_match[1] if uri.to_s.match(pattern)
end
# 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, page_res) do |match|
return @content_dir = match[1]
end
end
# 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
return @content_dir = 'wp-content' if default_content_dir_exists?
end
@content_dir
@@ -72,7 +71,7 @@ module WPScan
#
# @return [ String ]
def plugin_url(slug)
plugins_uri.join("#{URI.encode(slug)}/").to_s
plugins_uri.join("#{Addressable::URI.encode(slug)}/").to_s
end
# @return [ String ]
@@ -94,7 +93,7 @@ module WPScan
#
# @return [ String ]
def theme_url(slug)
themes_uri.join("#{URI.encode(slug)}/").to_s
themes_uri.join("#{Addressable::URI.encode(slug)}/").to_s
end
# @return [ String, False ] String of the sub_dir found, false otherwise
@@ -106,9 +105,12 @@ module WPScan
# url_pattern is from CMSScanner::Target
pattern = %r{#{url_pattern}(.+?)/(?:xmlrpc\.php|wp\-includes/)}i
xpath = '(//@src|//@href|//@data-src)[contains(., "xmlrpc.php") or contains(., "wp-includes/")]'
in_scope_uris(homepage_res) do |uri|
return @sub_dir = Regexp.last_match[1] if uri.to_s.match(pattern)
[homepage_res, error_404_res].each do |page_res|
in_scope_uris(page_res, xpath) do |uri|
return @sub_dir = Regexp.last_match[1] if uri.to_s.match(pattern)
end
end
@sub_dir = false

View File

@@ -2,5 +2,5 @@
# Version
module WPScan
VERSION = '3.7.2'
VERSION = '3.7.11'
end

View File

@@ -166,6 +166,7 @@ describe WPScan::Controller::Core do
before do
expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
expect(core.target).to receive(:wordpress_hosted?).and_return(false)
end
it 'calls the formatter when started and finished to update the db' do
@@ -174,56 +175,6 @@ describe WPScan::Controller::Core do
end
end
context 'when a redirect occurs' do
before do
stub_request(:any, target_url)
expect(core.target).to receive(:homepage_res)
.at_least(1)
.and_return(Typhoeus::Response.new(effective_url: redirection, body: ''))
end
context 'to the wp-admin/install.php' do
let(:redirection) { "#{target_url}wp-admin/install.php" }
it 'calls the formatter with the correct parameters and exit' do
expect(core.formatter).to receive(:output)
.with('not_fully_configured', hash_including(url: redirection), 'core').ordered
# TODO: Would be cool to be able to test the exit code
expect { core.before_scan }.to raise_error(SystemExit)
end
end
context 'to something else' do
let(:redirection) { 'http://g.com/' }
it 'raises an error' do
expect { core.before_scan }.to raise_error(CMSScanner::Error::HTTPRedirect)
end
end
context 'to another path with the wp-admin/install.php in the query' do
let(:redirection) { "#{target_url}index.php?a=/wp-admin/install.php" }
context 'when wordpress' do
it 'does not raise an error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
expect { core.before_scan }.to_not raise_error
end
end
context 'when not wordpress' 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
end
end
context 'when hosted on wordpress.com' do
let(:target_url) { 'http://ex.wordpress.com' }
@@ -234,52 +185,106 @@ describe WPScan::Controller::Core do
end
end
context 'when wordpress' do
before do
expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
end
context 'when not hosted on wordpress.com' do
before { allow(core.target).to receive(:wordpress_hosted?).and_return(false) }
it 'does not raise any error' do
expect { core.before_scan }.to_not raise_error
end
end
context 'when a redirect occurs' do
before do
stub_request(:any, target_url)
context 'when not wordpress' do
before do
expect(core).to receive(:load_server_module)
end
expect(core.target).to receive(:homepage_res)
.at_least(1)
.and_return(Typhoeus::Response.new(effective_url: redirection, body: ''))
end
context 'when no --force' do
before { expect(core.target).to receive(:maybe_add_cookies) }
context 'to the wp-admin/install.php' do
let(:redirection) { "#{target_url}wp-admin/install.php" }
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)
it 'calls the formatter with the correct parameters and exit' do
expect(core.formatter).to receive(:output)
.with('not_fully_configured', hash_including(url: redirection), 'core').ordered
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress)
# TODO: Would be cool to be able to test the exit code
expect { core.before_scan }.to raise_error(SystemExit)
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
context 'to something else' do
let(:redirection) { 'http://g.com/' }
it 'raises an error' do
expect { core.before_scan }.to raise_error(CMSScanner::Error::HTTPRedirect)
end
end
context 'to another path with the wp-admin/install.php in the query' do
let(:redirection) { "#{target_url}index.php?a=/wp-admin/install.php" }
context 'when wordpress' do
it 'does not raise an error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
expect { core.before_scan }.to_not raise_error
end
end
context 'when not wordpress' 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
end
end
context 'when wordpress' do
before do
expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
end
it 'does not raise any error' do
expect { core.before_scan }.to_not raise_error
end
end
context 'when not wordpress' do
before do
expect(core).to receive(:load_server_module)
end
context 'when no --force' do
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
context 'when --force' 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
end
context 'when --force' 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
end
end
end

View File

@@ -20,7 +20,7 @@ describe WPScan::Controller::CustomDirectories do
describe '#before_scan' do
context 'when the content_dir is not found and not supplied' do
before { expect(controller.target).to receive(:content_dir).with(:mixed) }
before { expect(controller.target).to receive(:content_dir).and_return(nil) }
it 'raises an exception' do
expect { controller.before_scan }.to raise_error(WPScan::Error::WpContentDirNotDetected)

View File

@@ -74,20 +74,40 @@ describe WPScan::Controller::VulnApi do
context 'when limited requests' do
let(:requests) { 100 }
it 'does not raise an error' do
it 'sets the token and does not raise an error' do
expect { controller.before_scan }.to_not raise_error
expect(WPScan::DB::VulnApi.token).to eql 'token'
end
context 'when unlimited requests' do
let(:requests) { 'Unlimited' }
it 'does not raise an error' do
it 'sets the token and does not raise an error' do
expect { controller.before_scan }.to_not raise_error
expect(WPScan::DB::VulnApi.token).to eql 'token'
end
end
end
end
end
end
context 'when token in ENV' do
before do
ENV[described_class::ENV_KEY] = 'token-from-env'
expect(WPScan::DB::VulnApi)
.to receive(:status)
.and_return('success' => true, 'plan' => 'free', 'requests_remaining' => 'Unlimited')
end
it 'sets the token and does not raise an error' do
expect { controller.before_scan }.to_not raise_error
expect(WPScan::DB::VulnApi.token).to eql 'token-from-env'
end
end
end
end

View File

@@ -9,7 +9,7 @@ describe WPScan::Finders::DbExports::KnownLocations do
describe '#potential_urls' do
before do
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
allow(target).to receive(:sub_dir).and_return(false)
end
it 'replace {domain_name} by its value' do
@@ -22,11 +22,45 @@ describe WPScan::Finders::DbExports::KnownLocations do
http://ex.lo/aa/backups/db_backup.sql
]
end
%w[dev poc www].each do |sub_domain|
context "when #{sub_domain} sub-domain" do
let(:url) { "https://#{sub_domain}.domain.tld" }
it 'replace {domain_name} by its correct value' do
expect(finder.potential_urls(opts).keys).to include "#{url}/domain.sql"
end
end
end
context 'when multi-level tlds' do
let(:url) { 'https://something.com.tr' }
it 'replace {domain_name} by its correct value' do
expect(finder.potential_urls(opts).keys).to include 'https://something.com.tr/something.sql'
end
end
context 'when multi-level tlds and sub-domain' do
let(:url) { 'https://dev.something.com.tr' }
it 'replace {domain_name} by its correct value' do
expect(finder.potential_urls(opts).keys).to include 'https://dev.something.com.tr/something.sql'
end
end
context 'when some weird stuff' do
let(:url) { 'https://098f6bcd4621d373cade4e832627b4f6.aa-bb-ccc-dd.domain-test.com' }
it 'replace {domain_name} by its correct value' do
expect(finder.potential_urls(opts).keys).to include "#{url}/domain-test.sql"
end
end
end
describe '#aggressive' do
before do
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
allow(target).to receive(:sub_dir).and_return(false)
expect(target).to receive(:head_or_get_params).and_return(method: :head)
finder.potential_urls(opts).each_key do |url|

View File

@@ -6,8 +6,55 @@ describe WPScan::Finders::InterestingFindings::MuPlugins do
let(:url) { 'http://ex.lo/' }
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'mu_plugins') }
before do
expect(target).to receive(:content_dir).at_least(1).and_return('wp-content')
end
describe '#passive' do
xit
before { stub_request(:get, url).to_return(body: body) }
context 'when no uris' do
let(:body) { '' }
its(:passive) { should be nil }
end
context 'when a large amount of unrelated uris' do
let(:body) do
Array.new(250) { |i| "<a href='#{url}#{i}.html'>Some Link</a><img src='#{url}img-#{i}.png'/>" }.join("\n")
end
it 'should not take a while to process the page' do
time_start = Time.now
result = finder.passive
time_end = Time.now
expect(result).to be nil
expect(time_end - time_start).to be < 1
end
end
context 'when uris' do
let(:body) { File.read(fixtures.join(fixture)) }
context 'when none matching' do
let(:fixture) { 'no_match.html' }
its(:passive) { should be nil }
end
context 'when matching via href' do
let(:fixture) { 'match_href.html' }
its(:passive) { should be_a WPScan::Model::MuPlugins }
end
context 'when matching from src' do
let(:fixture) { 'match_src.html' }
its(:passive) { should be_a WPScan::Model::MuPlugins }
end
end
end
describe '#aggressive' do

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
describe WPScan::Finders::MainTheme::CssStyleIn404Page do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { FINDERS_FIXTURES.join('main_theme', 'css_style_in_404_page') }
# This stuff is just a child class of CssStyleInHomepage (using the error_404_res rather than homepage_res)
# which already has a spec
end

View File

@@ -1,10 +1,10 @@
# frozen_string_literal: true
describe WPScan::Finders::MainTheme::CssStyle do
describe WPScan::Finders::MainTheme::CssStyleInHomepage do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { FINDERS_FIXTURES.join('main_theme', 'css_style') }
let(:fixtures) { FINDERS_FIXTURES.join('main_theme', 'css_style_in_homepage') }
describe '#passive' do
after do
@@ -33,7 +33,7 @@ describe WPScan::Finders::MainTheme::CssStyle do
@expected = WPScan::Model::Theme.new(
'twentyfifteen',
target,
found_by: 'Css Style (Passive Detection)',
found_by: 'Css Style In Homepage (Passive Detection)',
confidence: 70,
style_url: 'http://wp.lab/wp-content/themes/twentyfifteen/style.css?ver=4.1.1'
)
@@ -47,7 +47,7 @@ describe WPScan::Finders::MainTheme::CssStyle do
@expected = WPScan::Model::Theme.new(
'custom',
target,
found_by: 'Css Style (Passive Detection)',
found_by: 'Css Style In Homepage (Passive Detection)',
confidence: 70,
style_url: 'http://wp.lab/wp-content/themes/custom/style.css'
)

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
describe WPScan::Finders::MainTheme::UrlsIn404Page do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { FINDERS_FIXTURES.join('main_theme', 'urls_in_404_page') }
# This stuff is just a child class of URLsInHomepage (using the error_404_res rather than homepage_res)
# which already has a spec
end

View File

@@ -6,7 +6,8 @@ describe WPScan::Finders::MainTheme::UrlsInHomepage do
let(:url) { 'http://wp.lab/' }
let(:fixtures) { FINDERS_FIXTURES.join('main_theme', 'urls_in_homepage') }
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
it_behaves_like 'App::Finders::WpItems::UrlsInPage' do
let(:page_url) { url }
let(:type) { 'themes' }
let(:uniq_links) { false }
let(:uniq_codes) { false }
@@ -18,6 +19,8 @@ describe WPScan::Finders::MainTheme::UrlsInHomepage do
before do
stub_request(:get, /.*.css/)
stub_request(:get, target.url).to_return(body: File.read(fixtures.join('found.html')))
allow(target).to receive(:content_dir).and_return('wp-content')
end
it 'returns the expected Themes' do

View File

@@ -7,32 +7,50 @@ describe WPScan::Finders::MainTheme::WooFrameworkMetaGenerator do
let(:fixtures) { FINDERS_FIXTURES.join('main_theme', 'woo_framework_meta_generator') }
describe '#passive' do
after do
stub_request(:get, url).to_return(body: File.read(fixtures.join(@file)))
expect(finder.passive).to eql @expected
before do
stub_request(:get, url).to_return(body: File.read(fixtures.join(homepage_fixture)))
stub_request(:get, ERROR_404_URL_PATTERN).to_return(body: File.read(fixtures.join(error_404_fixture)))
end
context 'when no Woo generator' do
let(:homepage_fixture) { 'no_woo_generator.html' }
let(:error_404_fixture) { 'no_woo_generator.html' }
it 'returns nil' do
@file = 'no_woo_generator.html'
@expected = nil
expect(finder.passive).to eql nil
end
end
context 'when Woo generator' do
before do
expect(target).to receive(:content_dir).at_least(1).and_return('wp-content')
allow(target).to receive(:content_dir).and_return('wp-content')
stub_request(:get, "#{url}wp-content/themes/Merchant/style.css")
end
it 'returns the expected theme' do
@file = 'woo_generator.html'
@expected = WPScan::Model::Theme.new(
'Merchant', target,
found_by: 'Woo Framework Meta Generator (Passive Detection)',
confidence: 80
)
context 'from the homepage' do
let(:homepage_fixture) { 'woo_generator.html' }
let(:error_404_fixture) { 'no_woo_generator.html' }
it 'returns the expected theme' do
expect(finder.passive).to eql WPScan::Model::Theme.new(
'Merchant', target,
found_by: 'Woo Framework Meta Generator (Passive Detection)',
confidence: 80
)
end
end
context 'from the 404 page' do
let(:homepage_fixture) { 'no_woo_generator.html' }
let(:error_404_fixture) { 'woo_generator.html' }
it 'returns the expected theme' do
expect(finder.passive).to eql WPScan::Model::Theme.new(
'Merchant', target,
found_by: 'Woo Framework Meta Generator (Passive Detection)',
confidence: 80
)
end
end
end
end

View File

@@ -8,7 +8,7 @@ describe WPScan::Finders::MainTheme::Base do
describe '#finders' do
it 'contains the expected finders' do
expect(main_theme.finders.map { |f| f.class.to_s.demodulize })
.to eq %w[CssStyle WooFrameworkMetaGenerator UrlsInHomepage]
.to eq %w[CssStyleInHomepage CssStyleIn404Page WooFrameworkMetaGenerator UrlsInHomepage UrlsIn404Page]
end
end
end

View File

@@ -0,0 +1,49 @@
# frozen_string_literal: true
describe WPScan::Finders::Passwords::XMLRPC do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Model::XMLRPC.new(url) }
let(:url) { 'http://ex.lo/xmlrpc.php' }
RESPONSE_403_BODY = '<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>403</int></value>
</member>
<member>
<name>faultString</name>
<value><string>Incorrect username or password.</string></value>
</member>
</struct>
</value>
</fault>
</methodResponse>'
describe '#attack' do
context 'when no valid credentials' do
before do
stub_request(:post, url).to_return(status: status, body: RESPONSE_403_BODY)
finder.attack(users, %w[pwd])
end
let(:users) { %w[admin].map { |username| WPScan::Model::User.new(username) } }
context 'when status = 200' do
let(:status) { 200 }
its('progress_bar.log') { should be_empty }
end
context 'when status = 403' do
let(:status) { 403 }
its('progress_bar.log') { should be_empty }
end
end
end
end

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
describe WPScan::Finders::Plugins::UrlsIn404Page do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'https://wp.lab/' }
let(:fixtures) { FINDERS_FIXTURES.join('plugins', 'urls_in_404_page') }
# This stuff is just a child class of URLsInHomepage (using the error_404_res rather than homepage_res)
# which already has a spec
end

View File

@@ -3,14 +3,17 @@
describe WPScan::Finders::Plugins::UrlsInHomepage do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:url) { 'https://wp.lab/' }
let(:fixtures) { FINDERS_FIXTURES.join('plugins', 'urls_in_homepage') }
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
before { target.scope << 'sub.lab' }
it_behaves_like 'App::Finders::WpItems::UrlsInPage' do
let(:page_url) { url }
let(:type) { 'plugins' }
let(:uniq_links) { true }
let(:uniq_codes) { true }
let(:expected_from_links) { (1..4).map { |i| "dl-#{i}" } }
let(:expected_from_links) { (1..5).map { |i| "dl-#{i}" } }
let(:expected_from_codes) { (1..6).map { |i| "dc-#{i}" } }
end

View File

@@ -8,7 +8,7 @@ describe WPScan::Finders::Plugins::Base do
describe '#finders' do
it 'contains the expected finders' do
expect(plugins.finders.map { |f| f.class.to_s.demodulize })
.to eq %w[UrlsInHomepage HeaderPattern Comment Xpath BodyPattern JavascriptVar KnownLocations]
.to eq %w[UrlsInHomepage UrlsIn404Page HeaderPattern Comment Xpath BodyPattern JavascriptVar KnownLocations]
end
end
end

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
describe WPScan::Finders::Themes::UrlsIn404Page do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { FINDERS_FIXTURES.join('themes', 'urls_in_404_page') }
# This stuff is just a child class of URLsInHomepage (using the error_404_res rather than homepage_res)
# which already has a spec
end

View File

@@ -6,7 +6,10 @@ describe WPScan::Finders::Themes::UrlsInHomepage do
let(:url) { 'http://wp.lab/' }
let(:fixtures) { FINDERS_FIXTURES.join('themes', 'urls_in_homepage') }
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
# before { target.scope << 'sub.lab' }
it_behaves_like 'App::Finders::WpItems::UrlsInPage' do
let(:page_url) { url }
let(:type) { 'themes' }
let(:uniq_links) { true }
let(:uniq_codes) { true }

View File

@@ -8,7 +8,7 @@ describe WPScan::Finders::Themes::Base do
describe '#finders' do
it 'contains the expected finders' do
expect(themes.finders.map { |f| f.class.to_s.demodulize })
.to eq %w[UrlsInHomepage KnownLocations]
.to eq %w[UrlsInHomepage UrlsIn404Page KnownLocations]
end
end
end

View File

@@ -19,7 +19,7 @@ describe WPScan::Finders::Users::AuthorIdBruteForcing do
end
end
describe '#potential_username' do
describe '#username_from_response' do
[
'4.1.1', '4.1.1-permalink',
'3.0', '3.0-permalink',
@@ -32,6 +32,19 @@ describe WPScan::Finders::Users::AuthorIdBruteForcing do
expect(finder.username_from_response(res)).to eql 'admin'
end
end
context 'when a lot of unrelated links' do
it 'should not take a while to process the page' do
body = Array.new(300) { |i| "<a href='#{url}#{i}.html'>Some Link</a>" }.join("\n")
body << '<a href="https://wp.lab/author/test/">Link</a>'
time_start = Time.now
expect(finder.username_from_response(Typhoeus::Response.new(body: body))).to eql 'test'
time_end = Time.now
expect(time_end - time_start).to be < 1
end
end
end
describe '#display_name_from_body' do
@@ -50,7 +63,7 @@ describe WPScan::Finders::Users::AuthorIdBruteForcing do
end
context 'when no display_name' do
['4.1.1', '3.0', '2.9.2'].each do |file|
%w[4.9-span-tag 4.1.1 3.0 2.9.2].each do |file|
it "returns nil for #{file}-empty.html" do
body = File.read(fixtures.join("#{file}-empty.html"))

View File

@@ -16,12 +16,31 @@ describe WPScan::Finders::Users::AuthorPosts do
results = finder.potential_usernames(res)
expect(results).to eql([
['admin', 'Author Pattern', 100],
['admin display_name', 'Display Name', 30],
['editor', 'Author Pattern', 100],
['editor', 'Display Name', 30]
])
expect(results).to eql [
['admin', 'Author Pattern', 100],
['admin display_name', 'Display Name', 30],
['editor', 'Author Pattern', 100],
['editor', 'Display Name', 30]
]
end
context 'when a lot of unrelated uris' do
it 'should not take a while to process the page' do
body = Array.new(300) { |i| "<a href='#{url}#{i}.html'>Some Link</a>" }.join("\n")
body << "<a href='#{url}author/admin/'>Other Link</a>"
body << "<a href='#{url}?author=2'>user display name</a>"
time_start = Time.now
results = finder.potential_usernames(Typhoeus::Response.new(body: body))
time_end = Time.now
expect(results).to eql [
['admin', 'Author Pattern', 100],
['user display name', 'Display Name', 30]
]
expect(time_end - time_start).to be < 1
end
end
end
end

View File

@@ -19,15 +19,17 @@ describe WPScan::Finders::Users::OembedApi do
end
context 'when a JSON response' do
let(:body) { File.read(fixture) }
context 'when 404' do
let(:body) { File.read(fixtures.join('404.json')) }
let(:fixture) { fixtures.join('404.json') }
its(:aggressive) { should eql([]) }
end
context 'when 200' do
context 'when author_url present' do
let(:body) { File.read(fixtures.join('200_author_url.json')) }
let(:fixture) { fixtures.join('200_author_url.json') }
it 'returns the expected array of users' do
users = finder.aggressive
@@ -44,7 +46,7 @@ describe WPScan::Finders::Users::OembedApi do
end
context 'when author_url not present but author_name' do
let(:body) { File.read(fixtures.join('200_author_name.json')) }
let(:fixture) { fixtures.join('200_author_name.json') }
it 'returns the expected array of users' do
users = finder.aggressive
@@ -59,6 +61,12 @@ describe WPScan::Finders::Users::OembedApi do
expect(user.interesting_entries).to eql ['http://wp.lab/wp-json/oembed/1.0/embed?url=http://wp.lab/&format=json']
end
end
context 'when body is an array' do
let(:fixture) { fixtures.join('array.json') }
its(:aggressive) { should eql([]) }
end
end
end
end

View File

@@ -87,6 +87,8 @@ describe WPScan::Finders::Users::WpJsonApi do
describe '#api_url' do
let(:fixtures) { super().join('api_url') }
before { allow(target).to receive(:sub_dir).and_return(false) }
context 'when url in the homepage' do
{
in_scope: 'https://wp.lab/wp-json/wp/v2/users/',
@@ -100,7 +102,7 @@ describe WPScan::Finders::Users::WpJsonApi do
end
context 'when subdir' do
before { allow(target).to receive(:subdir).and_return('cms') }
before { allow(target).to receive(:sub_dir).and_return('cms') }
{
in_scope_subdir: 'https://wp.lab/cms/wp-json/wp/v2/users/',

View File

@@ -10,10 +10,9 @@ describe WPScan::Model::Theme do
before { expect(blog).to receive(:content_dir).at_least(1).and_return('wp-content') }
describe '#new' do
before do
stub_request(:get, /.*\.css\z/)
.to_return(body: File.read(fixtures.join('style.css')))
end
before { stub_request(:get, /.*\.css\z/).to_return(body: File.read(fixture)) }
let(:fixture) { fixtures.join('style.css') }
its(:url) { should eql 'http://wp.lab/wp-content/themes/spec/' }
its(:style_url) { should eql 'http://wp.lab/wp-content/themes/spec/style.css' }
@@ -34,6 +33,14 @@ describe WPScan::Model::Theme do
its(:style_url) { should eql opts[:style_url] }
end
context 'when some new lines are stripped' do
let(:fixture) { fixtures.join('stripped_new_lines.css') }
its(:style_name) { should eql 'Divi' }
its(:style_uri) { should eql 'http://www.elegantthemes.com/gallery/divi/' }
its(:license_uri) { should eql 'http://www.gnu.org/licenses/gpl-2.0.html' }
end
end
describe '#version' do

View File

@@ -46,7 +46,7 @@ describe WPScan::Model::WpItem do
end
it 'encodes the path' do
expect(wp_item.url('#t#')).to eql "#{item_url}%23t%23"
expect(wp_item.url('#t#')).to eql "#{item_url}#t%23"
expect(wp_item.url('t .txt')).to eql "#{item_url}t%20.txt"
end
end

View File

@@ -1,4 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
!.gitignore

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
msgid ""
msgstr ""
"Project-Id-Version: Woo Pelecard v1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-07-07 07:09+0200\n"
"PO-Revision-Date: 2014-07-07 07:09+0200\n"
"Last-Translator: Tzvi Rabinovitch <tzvi.ra@gmail.com>\n"
"Language-Team: \n"
"Language: he_IL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Poedit 1.5.4\n"
"X-Poedit-SourceCharset: UTF-8\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-Poedit-Basepath: .\n"
"X-Textdomain-Support: yes\n"
"X-Poedit-SearchPath-0: ..\n"
#: ../10bit-easycard-paybuttons-options.php:18
msgid "Settings saved."
msgstr "שמרתי את ההגדרות."
#: ../10bit-easycard-paybuttons-options.php:23
msgid "10Bit EasyCard PayButtons Settings"
msgstr "כפתורי תשלום איזיקארד"
#: ../10bit-easycard-paybuttons-options.php:37
msgid "Client ID"
msgstr "מזהה לקוח"
# @ TenBit_woo_pelecard
#: ../10bit-easycard-paybuttons-options.php:45
msgid "Password"
msgstr "סיסמה"
#: ../10bit-easycard-paybuttons-options.php:53
msgid "Maximum Payments"
msgstr "מספר תשלמים מקסימלי"
#: ../10bit-easycard-paybuttons-options.php:64
msgid "Save Changes"
msgstr "שמור שינויים"
#: ../10bit-easycard-paybuttons-options.php:70
msgid "Usage :"
msgstr "שימוש"
#: ../10bit-easycard-paybuttons-options.php:72
msgid "Add the folloing short code inside a post or a page :"
msgstr "הוסיפו את השורטקוד הבא לדף או לעמוד באתר"
#: ../10bit-easycard-paybuttons-options.php:76
msgid "value : The amount to pay"
msgstr "value : הסכום לתשלום"
#: ../10bit-easycard-paybuttons-options.php:78
msgid "item_name : the name of the sold item"
msgstr "item_name : שם המוצר למכירה"
#: ../10bit-easycard-paybuttons-options.php:80
msgid "button_class : CSS class for styling"
msgstr "button_class : קלאס CSS לעיצוב"
#: ../10bit-easycard-paybuttons-options.php:82
msgid "button_text : Text to show on the button"
msgstr "button_text : הטקסט שיופיע על הכפתור"
#: ../10bit-paybuttons-easycard.php:29
msgid "EasyCard Pay Buttons"
msgstr "כפתורי תשלום איזיקארד"
# @ TenBit_woo_pelecard
#~ msgid "License Key"
#~ msgstr "מפתח"
#~ msgid "Valid"
#~ msgstr "תקין"
#~ msgid "Invalid"
#~ msgstr "לא תקין"
#, fuzzy
#~ msgid "Leave blank for not sending a copy"
#~ msgstr "השאר ריק במידה ואינך מעוניים בהעתק"
#, fuzzy
#~ msgid "10Bit iCount Settings"
#~ msgstr "הגדרות icount"
#~ msgid "Easycard"
#~ msgstr "איזיקארד"

View File

@@ -0,0 +1,132 @@
msgid ""
msgstr ""
"Project-Id-Version: Woo Pelecard v1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-07-09 01:31+0200\n"
"PO-Revision-Date: 2014-07-09 01:32+0200\n"
"Last-Translator: Tzvi Rabinovitch <tzvi.ra@gmail.com>\n"
"Language-Team: \n"
"Language: he_IL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Poedit 1.5.4\n"
"X-Poedit-SourceCharset: UTF-8\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-Poedit-Basepath: .\n"
"X-Textdomain-Support: yes\n"
"X-Poedit-SearchPath-0: ..\n"
# @ TenBit_woo_pelecard
#: ../10bit-paybuttons-pelecard.php:28
msgid "pelecard Pay Buttons"
msgstr "כפתורי תשלום פלאכארד"
#: ../10bit-pelecard-paybuttons-options.php:68
msgid "Settings saved."
msgstr "שמרתי את ההגדרות."
#: ../10bit-pelecard-paybuttons-options.php:73
msgid "10Bit pelecard PayButtons Settings"
msgstr "כפתורי תשלום פלאכארד"
# @ TenBit_woo_pelecard
#: ../10bit-pelecard-paybuttons-options.php:87
msgid "Terminal Number"
msgstr "מספר מסוף סליקה"
# @ TenBit_woo_pelecard
#: ../10bit-pelecard-paybuttons-options.php:95
msgid "Username"
msgstr "שם משתמש"
# @ TenBit_woo_pelecard
#: ../10bit-pelecard-paybuttons-options.php:103
msgid "Password"
msgstr "סיסמה"
#: ../10bit-pelecard-paybuttons-options.php:111
msgid "Maximum Payments"
msgstr "מספר תשלמים מקסימלי"
#: ../10bit-pelecard-paybuttons-options.php:119
msgid "Currency"
msgstr "מטבע"
#: ../10bit-pelecard-paybuttons-options.php:123
msgid "ILS"
msgstr "ש\"ח"
#: ../10bit-pelecard-paybuttons-options.php:124
msgid "USD"
msgstr "דולר"
#: ../10bit-pelecard-paybuttons-options.php:130
msgid "Success ( thank you ) page URL"
msgstr "כתובת הצלחה ( דף תודה )"
#: ../10bit-pelecard-paybuttons-options.php:138
msgid "Error page URL"
msgstr "כתובת כשלון"
#: ../10bit-pelecard-paybuttons-options.php:146
msgid "Path to custom logo"
msgstr "קישור ללוגו "
#: ../10bit-pelecard-paybuttons-options.php:154
msgid "Path to small custom logo"
msgstr "קישור ללוגו קטן "
#: ../10bit-pelecard-paybuttons-options.php:162
msgid "Hide PCI DSS logo"
msgstr "הסתר את הלוגו של PCI DSS"
#: ../10bit-pelecard-paybuttons-options.php:170
msgid "Hide Pelecard logo"
msgstr "הסתר את לוגו פלאכארד"
#: ../10bit-pelecard-paybuttons-options.php:178
msgid "Path To custom Style sheet(CSS)"
msgstr "כתובת כשלון"
#: ../10bit-pelecard-paybuttons-options.php:183
msgid "must be a secured URL ( HTTPS )"
msgstr "חייב להיות מכתובת מאובטחת (HTTPS )"
#: ../10bit-pelecard-paybuttons-options.php:189
msgid "Background color"
msgstr "צבע רקע"
#: ../10bit-pelecard-paybuttons-options.php:195
msgid "Use hexadecimal color without the #"
msgstr "ערך הקסדצימלי ללא #"
#: ../10bit-pelecard-paybuttons-options.php:217
msgid "Save Changes"
msgstr "שמור שינויים"
#: ../10bit-pelecard-paybuttons-options.php:223
msgid "Usage :"
msgstr "שימוש"
#: ../10bit-pelecard-paybuttons-options.php:225
msgid "Add the following short code inside a post or a page :"
msgstr "הוסיפו את השורטקוד הבא לדף או לעמוד באתר"
#: ../10bit-pelecard-paybuttons-options.php:229
msgid "value : The amount to pay"
msgstr "value : הסכום לתשלום"
#: ../10bit-pelecard-paybuttons-options.php:231
msgid "item_name : the name of the sold item"
msgstr "item_name : שם המוצר למכירה"
#: ../10bit-pelecard-paybuttons-options.php:233
msgid "button_class : CSS class for styling"
msgstr "button_class : קלאס CSS לעיצוב"
#: ../10bit-pelecard-paybuttons-options.php:235
msgid "button_text : Text to show on the button"
msgstr "button_text : הטקסט שיופיע על הכפתור"

View File

@@ -0,0 +1,24 @@
# Italian translation for ab-human-time
# Copyright (C) 2014 AB Human Time
# This file is distributed under the same license as the AB Human Time package.
msgid ""
msgstr ""
"Project-Id-Version: AB Human Time 0.1\n"
"POT-Creation-Date: 2014-02-26 20:13+0100\n"
"PO-Revision-Date: 2014-02-26 21:25+0100\n"
"Last-Translator: endrix.develop <endrix.develop@gmail.com>\n"
"Language-Team: <endrix.develop@gmail.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.6.4\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: it_IT\n"
#: ../ab-human-time.php:21
msgid "Published "
msgstr "Pubblicato "
#: ../ab-human-time.php:23
msgid " ago"
msgstr " fa"

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 ""

View File

@@ -0,0 +1,112 @@
# Copyright (C) 2016 Kailey Lampert
# This file is distributed under the same license as the PACKAGE package.
# Kailey Lampert <trepmal@gmail.com>, 2016.
msgid ""
msgstr ""
"Project-Id-Version: 1.7\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-08 17:48-0700\n"
"PO-Revision-Date: 2016-09-08 17:48-0700\n"
"Last-Translator: Kailey Lampert <trepmal@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: active-plugins.php:62
msgid "Acitve Plugins is for multisite use only."
msgstr ""
#: active-plugins.php:72 active-plugins.php:83
msgid "Active Plugins Across Network"
msgstr ""
#: active-plugins.php:72
msgid "Active Plugins"
msgstr ""
#: active-plugins.php:86
#, php-format
msgid "<a href=\"%s\">Network-Activated Plugins</a>"
msgstr ""
#: active-plugins.php:87
#, php-format
msgid "<a href=\"%s\">MU Plugins</a>"
msgstr ""
#: active-plugins.php:90
#, php-format
msgid "List does not include: %s"
msgstr ""
#: active-plugins.php:146
msgid ""
"Totals <span class=\"description\">each active plugin and how many users</"
"span>"
msgstr ""
#: active-plugins.php:176 active-plugins.php:213
#, php-format
msgid "v%s"
msgstr ""
#: active-plugins.php:180 active-plugins.php:214
#, php-format
msgid "%1$s %2$s"
msgstr ""
#: active-plugins.php:182
#, php-format
msgid "%s (Uninstalled)"
msgstr ""
#: active-plugins.php:187
#, php-format
msgid " (tagged: %s)"
msgstr ""
#: active-plugins.php:197
msgid "Select all"
msgstr ""
#: active-plugins.php:198
msgid "Deselect all"
msgstr ""
#: active-plugins.php:199
msgid "Toggle"
msgstr ""
#: active-plugins.php:209
msgid "Plugins with zero (0) users:"
msgstr ""
#: active-plugins.php:217
msgid "none"
msgstr ""
#: active-plugins.php:224
msgid "Show sites with no active plugins"
msgstr ""
#: active-plugins.php:235
msgid "Edit"
msgstr ""
#: active-plugins.php:236
msgid "View"
msgstr ""
#: active-plugins.php:237
msgid "Dashboard"
msgstr ""
#: active-plugins.php:238
msgid "Plugins"
msgstr ""
#: active-plugins.php:249
msgid "(network-activated)"
msgstr ""

View File

@@ -0,0 +1,619 @@
# Copyright (C) 2019 RedNao
# This file is distributed under the same license as the Extra Product Options Builder for WooCommerce plugin.
msgid ""
msgstr ""
"Project-Id-Version: Extra Product Options Builder for WooCommerce 1.2.11\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/woo-extra-products\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-11-02T18:08:21+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.3.0\n"
"X-Domain: rednaowooextraproduct\n"
#. Plugin Name of the plugin
msgid "Extra Product Options Builder for WooCommerce"
msgstr ""
#. Plugin URI of the plugin
msgid "http://smartforms.rednao.com/getit"
msgstr ""
#. Description of the plugin
msgid "Additional product fields for woocommerce"
msgstr ""
#. Author of the plugin
msgid "RedNao"
msgstr ""
#. Author URI of the plugin
msgid "http://rednao.com"
msgstr ""
#: jstranslations/InternalShared.php:2
msgid "Jan"
msgstr ""
#: jstranslations/InternalShared.php:3
msgid "Feb"
msgstr ""
#: jstranslations/InternalShared.php:4
msgid "Mar"
msgstr ""
#: jstranslations/InternalShared.php:5
msgid "Apr"
msgstr ""
#: jstranslations/InternalShared.php:6
msgid "May"
msgstr ""
#: jstranslations/InternalShared.php:7
msgid "Jun"
msgstr ""
#: jstranslations/InternalShared.php:8
msgid "Jul"
msgstr ""
#: jstranslations/InternalShared.php:9
msgid "Aug"
msgstr ""
#: jstranslations/InternalShared.php:10
msgid "Sep"
msgstr ""
#: jstranslations/InternalShared.php:11
msgid "Oct"
msgstr ""
#: jstranslations/InternalShared.php:12
msgid "Nov"
msgstr ""
#: jstranslations/InternalShared.php:13
msgid "Dec"
msgstr ""
#: jstranslations/InternalShared.php:14
msgid "January"
msgstr ""
#: jstranslations/InternalShared.php:15
msgid "February"
msgstr ""
#: jstranslations/InternalShared.php:16
msgid "March"
msgstr ""
#: jstranslations/InternalShared.php:17
msgid "April"
msgstr ""
#: jstranslations/InternalShared.php:18
msgid "June"
msgstr ""
#: jstranslations/InternalShared.php:19
msgid "July"
msgstr ""
#: jstranslations/InternalShared.php:20
msgid "August"
msgstr ""
#: jstranslations/InternalShared.php:21
msgid "September"
msgstr ""
#: jstranslations/InternalShared.php:22
msgid "October"
msgstr ""
#: jstranslations/InternalShared.php:23
msgid "November"
msgstr ""
#: jstranslations/InternalShared.php:24
msgid "December"
msgstr ""
#: jstranslations/InternalShared.php:25
msgid "Su"
msgstr ""
#: jstranslations/InternalShared.php:26
msgid "Mo"
msgstr ""
#: jstranslations/InternalShared.php:27
msgid "Tu"
msgstr ""
#: jstranslations/InternalShared.php:28
msgid "We"
msgstr ""
#: jstranslations/InternalShared.php:29
msgid "Th"
msgstr ""
#: jstranslations/InternalShared.php:30
msgid "Fr"
msgstr ""
#: jstranslations/InternalShared.php:31
msgid "Sa"
msgstr ""
#: jstranslations/InternalShared.php:32
msgid "Sun"
msgstr ""
#: jstranslations/InternalShared.php:33
msgid "Mon"
msgstr ""
#: jstranslations/InternalShared.php:34
msgid "Tue"
msgstr ""
#: jstranslations/InternalShared.php:35
msgid "Wed"
msgstr ""
#: jstranslations/InternalShared.php:36
msgid "Thu"
msgstr ""
#: jstranslations/InternalShared.php:37
msgid "Fri"
msgstr ""
#: jstranslations/InternalShared.php:38
msgid "Sat"
msgstr ""
#: jstranslations/InternalShared.php:39
#: jstranslations/ProductFieldBuilder.php:97
msgid "Sunday"
msgstr ""
#: jstranslations/InternalShared.php:40
#: jstranslations/ProductFieldBuilder.php:98
msgid "Monday"
msgstr ""
#: jstranslations/InternalShared.php:41
#: jstranslations/ProductFieldBuilder.php:99
msgid "Tuesday"
msgstr ""
#: jstranslations/InternalShared.php:42
#: jstranslations/ProductFieldBuilder.php:100
msgid "Wednesday"
msgstr ""
#: jstranslations/InternalShared.php:43
#: jstranslations/ProductFieldBuilder.php:101
msgid "Thursday"
msgstr ""
#: jstranslations/InternalShared.php:44
#: jstranslations/ProductFieldBuilder.php:102
msgid "Friday"
msgstr ""
#: jstranslations/InternalShared.php:45
#: jstranslations/ProductFieldBuilder.php:103
msgid "Saturday"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:2
msgid "Please select a field"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:3
msgid "Cancel"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:4
msgid "Import"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:5
msgid "Export"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:6
#: ProductFieldBuilder.php:1
msgid "Label"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:7
msgid "Image URL"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:8
msgid "Price"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:9
msgid "Sale"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:10
msgid "Price Type"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:11
msgid "Fixed amount"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:12
msgid "% of original price"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:13
msgid "% of original price + options"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:14
msgid "Settings"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:15
msgid "Conditions"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:16
msgid "Enable Show/Hide Conditions"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:17
msgid "Show"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:18
msgid "Hide"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:19
msgid "this field if"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:20
msgid "Select a field"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:21
msgid "Fields"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:22
msgid "AND"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:23
msgid "or"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:24
msgid "Add new group"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:25
msgid "Select one"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:26
msgid "Equal to"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:27
msgid "Not Equal to"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:28
msgid "Is Empty"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:29
msgid "Is Not Empty"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:30
msgid "Contains"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:31
msgid "Not Contains"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:32
msgid "Default text"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:33
#: ProductFieldBuilder.php:1
msgid "Placeholder"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:34
#: ProductFieldBuilder.php:1
msgid "Required"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:35
#: ProductFieldBuilder.php:1
msgid "Show quantity selector"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:36
#: ProductFieldBuilder.php:1
msgid "Quantity Position"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:37
msgid "Left"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:38
msgid "Right"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:39
msgid "Top"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:40
msgid "Bottom"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:41
#: ProductFieldBuilder.php:1
msgid "Default value"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:42
#: ProductFieldBuilder.php:1
msgid "Quantity Label"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:43
#: ProductFieldBuilder.php:1
msgid "0 = No Maximum"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:44
#: ProductFieldBuilder.php:1
msgid "Maximum Value"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:45
#: ProductFieldBuilder.php:1
msgid "0 = No Minimum"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:46
#: ProductFieldBuilder.php:1
msgid "Minimum Value"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:47
msgid "Price type"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:48
msgid "None (don't use this field to calculate price)"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:49
msgid "Fixed Amount"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:50
#: ProductFieldBuilder.php:1
msgid "Quantity"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:51
msgid "Current value"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:52
msgid "Percent of the original price"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:53
msgid "Percent of the original price + options"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:54
msgid "Price per word"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:55
msgid "Price per char"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:56
msgid "Sale Price (Empty = No Sale)"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:57
msgid "Percentage"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:58
msgid "Sale Percentage"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:59
msgid "Free chars"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:60
msgid "Ignore Spaces"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:61
msgid "Free words"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:62
#: ProductFieldBuilder.php:1
msgid "Hide price"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:63
#: ProductFieldBuilder.php:1
msgid "General"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:64
#: ProductFieldBuilder.php:1
msgid "Pricing"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:65
msgid "Text"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:66
#: ProductFieldBuilder.php:1
msgid "Options"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:67
msgid "Phone: (999)99-999-999"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:68
msgid "Credit Card: 9999 9999 9999 9999"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:69
msgid "Custom"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:70
msgid "9=Numbers, a=letters, *=Numbers or letters"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:71
msgid "Custom Mask"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:72
msgid "Mask Char"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:73
msgid "Image Width"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:74
msgid "Image Height"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:75
msgid "Allow Multiple"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:76
msgid "Horizontal"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:77
msgid "Vertical"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:78
#: ProductFieldBuilder.php:1
msgid "Date Format"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:79
msgid "Price Per Day"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:80
msgid "Label (Start Date)"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:81
msgid "Placeholder (Start Date)"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:82
msgid "Default Date (Start Date)"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:83
msgid "This property support two type of fields"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:84
msgid "A number, representing the number of dates from now e.g. 0 for today 1 for tomorrow"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:85
msgid "2 for the day after tomorrow and so on. It supports negative numbers as well"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:86
msgid "An specific date in the format of YYYY/MM/DD e.g. 2000/02/01 for February first of 2000"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:87
msgid "Start Date"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:88
msgid "Label (End Date)"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:89
msgid "End Date"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:90
msgid "Title"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:91
msgid "Style"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:92
msgid "Dashed"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:93
msgid "Solid"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:94
msgid "Color"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:95
msgid "Default Date"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:96
msgid "Week Start On"
msgstr ""
#: jstranslations/ProductFieldBuilder.php:104
msgid "Default Color"
msgstr ""

View File

@@ -0,0 +1,428 @@
# Copyright (C) 2012
# This file is distributed under the same license as the package.
msgid ""
msgstr ""
"Project-Id-Version: Advanced Category Column\n"
"Report-Msgid-Bugs-To: http://wordpress.org/tag/advanced-category-column\n"
"POT-Creation-Date: 2016-02-17 11:35+0200\n"
"PO-Revision-Date: 2016-02-17 11:36+0200\n"
"Last-Translator: Stefan Crämer <translate@atelier-fuenf.de>\n"
"Language-Team: Waldemar Stoffel <stoffel@atelier-fuenf.de>\n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Generator: Poedit 1.8.1\n"
"X-Poedit-Basepath: ..\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
"_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SearchPath-0: .\n"
#: advanced-cc.php:112
msgid "FAQ"
msgstr "FAQ"
#: advanced-cc.php:113
msgid "Donate"
msgstr "Donar"
#: advanced-cc.php:123 class-lib/A5_OptionPageClass.php:31
#: class-lib/ACC_AdminClass.php:35
msgid "Settings"
msgstr "Ajustes"
#: class-lib/A5_ImageClass.php:48
msgid "Permalink to"
msgstr "enlace permanente a"
#: class-lib/A5_OptionPageClass.php:145
msgid "Click to toggle"
msgstr ""
#: class-lib/A5_OptionPageClass.php:382
msgid "Not set"
msgstr ""
#: class-lib/A5_WidgetClass.php:37
msgid "Homepage"
msgstr "Página de Inicio"
#: class-lib/A5_WidgetClass.php:38
msgid "Frontpage (e.g. a static page as homepage)"
msgstr ""
"Página Inicial (por ejemplo, una página estática como página de inicio)"
#: class-lib/A5_WidgetClass.php:39
msgid "&#34;Page&#34; pages"
msgstr "&#34;Pagína&#34; páginas"
#: class-lib/A5_WidgetClass.php:40
msgid "Category pages"
msgstr "Categoría de páginas"
#: class-lib/A5_WidgetClass.php:41
msgid "Single post pages"
msgstr "Páginas de post simples"
#: class-lib/A5_WidgetClass.php:42
msgid "Archive pages"
msgstr "Páginas de Archivo"
#: class-lib/A5_WidgetClass.php:43
#, fuzzy
msgid "Post type archives"
msgstr "Páginas de post simples"
#: class-lib/A5_WidgetClass.php:44
msgid "Tag pages"
msgstr "Páginas de Etiquetas"
#: class-lib/A5_WidgetClass.php:45
msgid "Attachments"
msgstr "Adjuntos"
#: class-lib/A5_WidgetClass.php:46
msgid "Custom Taxonomy pages (only available, if having a plugin)"
msgstr ""
"Páginas de Taxonomía Personalizada (sólo está disponible si tiene un plugin)"
#: class-lib/A5_WidgetClass.php:47
msgid "Author pages"
msgstr "Páginas del autor"
#: class-lib/A5_WidgetClass.php:48
msgid "Search Results"
msgstr "Buscar Resultados"
#: class-lib/A5_WidgetClass.php:49
msgid "&#34;Not Found&#34;"
msgstr "&#34;No Encontrado&#34;"
#: class-lib/A5_WidgetClass.php:52
#, fuzzy
msgid "Login Page (only available, if having a plugin)"
msgstr ""
"Páginas de Taxonomía Personalizada (sólo está disponible si tiene un plugin)"
#: class-lib/A5_WidgetClass.php:54
msgid "Check all"
msgstr "Seleccionar todo"
#: class-lib/A5_WidgetClass.php:56
msgid ""
"Check, where you want to show the widget. By default, it is showing on the "
"homepage and the category pages:"
msgstr ""
"Seleccione, dónde desea mostrar el widget. Por defecto, se muestra en la "
"página principal y en las páginas de la categoría:"
#: class-lib/A5_WidgetClass.php:92
msgid "Under image"
msgstr ""
#: class-lib/A5_WidgetClass.php:92
msgid "Left of image"
msgstr ""
#: class-lib/A5_WidgetClass.php:92
msgid "Right of image"
msgstr ""
#: class-lib/A5_WidgetClass.php:92
msgid "Don&#39;t show excerpt"
msgstr ""
#: class-lib/A5_WidgetClass.php:94
msgid ""
"Choose, whether or not to display the excerpt and whether it comes under the "
"thumbnail or next to it."
msgstr ""
#: class-lib/A5_WidgetClass.php:104
msgid "Weight of the Post Title:"
msgstr "Peso del título del Post:"
#: class-lib/A5_WidgetClass.php:108
msgid "Left"
msgstr ""
#: class-lib/A5_WidgetClass.php:108
msgid "Right"
msgstr ""
#: class-lib/A5_WidgetClass.php:108
msgid "Center"
msgstr ""
#: class-lib/A5_WidgetClass.php:108
msgid "Justify"
msgstr ""
#: class-lib/A5_WidgetClass.php:110
msgid "How do you want to align the Post Title?"
msgstr ""
#: class-lib/A5_WidgetClass.php:121
msgid ""
"Check to have an additional &#39;read more&#39; link at the end of the "
"excerpt."
msgstr ""
#: class-lib/A5_WidgetClass.php:122
#, php-format
msgid ""
"Write here some text for the &#39;read more&#39; link. By default, it is %s:"
msgstr ""
#: class-lib/A5_WidgetClass.php:123
msgid ""
"If you want to style the &#39;read more&#39; link, you can enter a class "
"here."
msgstr ""
#: class-lib/ACC_AdminClass.php:63
msgid ""
"http://wasistlos.waldemarstoffel.com/plugins-fur-wordpress/advanced-category-"
"column-plugin"
msgstr ""
"http://wasistlos.waldemarstoffel.com/plugins-fur-wordpress/advanced-category-"
"column-plugin"
#: class-lib/ACC_AdminClass.php:63
msgid "Plugin Support"
msgstr ""
#: class-lib/ACC_AdminClass.php:65
msgid ""
"Style the links of the widget. If you leave this empty, your theme will "
"style the hyperlinks."
msgstr ""
"El estilo de los enlaces del widget. Si deja el campo vacío, el tema será el "
"mismo estilo de los hipervínculos."
#: class-lib/ACC_AdminClass.php:67
msgid "Just input something like,"
msgstr "Sólo algo de entrada como,"
#: class-lib/ACC_AdminClass.php:71
msgid "to get fat, blue, underlined links."
msgstr "Los enlaces serán, azul subrayado."
#: class-lib/ACC_AdminClass.php:73
msgid ""
"You most probably have to use &#34;!important&#34; at the end of each line, "
"to make it work."
msgstr ""
"Lo más probable es usar &#34;!important&#34; al final de cada línea, para "
"hacer que funcione."
#: class-lib/ACC_AdminClass.php:86
msgid "Debug Info"
msgstr ""
#: class-lib/ACC_AdminClass.php:105
msgid "Styling of the links"
msgstr "Estilo de los enlaces"
#: class-lib/ACC_AdminClass.php:107
msgid "Link style:"
msgstr "Estílo enlace:"
#: class-lib/ACC_AdminClass.php:109
msgid "Hover style:"
msgstr "Estilo hover:"
#: class-lib/ACC_AdminClass.php:111
msgid "Widget container:"
msgstr ""
#: class-lib/ACC_AdminClass.php:111
msgid ""
"You can enter your own style for the widgets here. This will overwrite the "
"styles of your theme."
msgstr ""
#: class-lib/ACC_AdminClass.php:111
msgid ""
"If you leave this empty, you can still style every instance of the widget "
"individually."
msgstr ""
#: class-lib/ACC_AdminClass.php:113
#, fuzzy
msgid "Compress Style Sheet:"
msgstr "Estílo enlace:"
#: class-lib/ACC_AdminClass.php:113
msgid "Click here to compress the style sheet."
msgstr ""
#: class-lib/ACC_AdminClass.php:115
msgid "Debug:"
msgstr ""
#: class-lib/ACC_AdminClass.php:115
msgid ""
"If you can&#39;t reach the dynamical style sheet, you&#39;ll have to display "
"the styles inline. By clicking here you can do so."
msgstr ""
#: class-lib/ACC_AdminClass.php:119
msgid "entries"
msgstr ""
#: class-lib/ACC_AdminClass.php:119
msgid "entry"
msgstr ""
#: class-lib/ACC_AdminClass.php:121
#, php-format
msgid "Empty cache (%d %s):"
msgstr ""
#: class-lib/ACC_AdminClass.php:121
msgid "You can empty the plugin&#39;s cache here, if necessary."
msgstr ""
#: class-lib/ACC_AdminClass.php:129
msgid "Just put some css code here."
msgstr "Sólo hay que poner algo de código CSS aquí."
#: class-lib/ACC_AdminClass.php:189
msgid "Cache emptied."
msgstr ""
#: class-lib/ACC_WidgetClass.php:18
msgid ""
"Configure the output and looks of the widget. Then display thumbnails and "
"excerpts of posts in your sidebars and define, on what kind of pages they "
"will show."
msgstr ""
"Configure la salida y la apariencia del widget. Entonces se mostrarán las "
"miniaturas y extractos de los mensajes en las barras laterales y se definirá "
"en qué tipo de páginas se mostrarán."
#: class-lib/ACC_WidgetClass.php:108
msgid "Title:"
msgstr "Título:"
#: class-lib/ACC_WidgetClass.php:109
#, php-format
msgid ""
"To exclude certain categories or to show just a special category, simply "
"write their ID&#39;s separated by comma (e.g. %s-5, 2, 4%s will show "
"categories 2 and 4 and will exclude category 5):"
msgstr ""
"Para excluir ciertas categorías o para mostrar sólo una categoría especial, "
"basta con escribir su ID separado por coma (por ejemplo,%s-5, 2, 4%s "
"mostrará las categorías 2 y 4, y se excluye la categoría 5):"
#: class-lib/ACC_WidgetClass.php:110
msgid "Check to show the categories in which the post is filed."
msgstr "Seleccione para mostrar las categorías en que se presenta el mensaje."
#: class-lib/ACC_WidgetClass.php:111
msgid ""
"Give some text that you want in front of the post&#39;s categtories (i.e "
"&#39;filed under&#39;:"
msgstr ""
"De algún texto que usted quiere al frente de la categoría de mensajes (ej. "
"&#39;llenado debajo&#39;:"
#: class-lib/ACC_WidgetClass.php:112
msgid "How many posts will be displayed in the sidebar:"
msgstr "Cuántos post se mostrarán en la barra lateral:"
#: class-lib/ACC_WidgetClass.php:113
msgid "Offset (how many posts are spared out in the beginning):"
msgstr "Offset (cuántos post están a salvo en el inicio):"
#: class-lib/ACC_WidgetClass.php:114
msgid "Check to have the offset only on your homepage."
msgstr ""
"Verificación para que el desplazamiento sólo sea en la página principal."
#: class-lib/ACC_WidgetClass.php:115
msgid "Width of the thumbnail (in px):"
msgstr "Ancho de las miniaturas (en px)"
#: class-lib/ACC_WidgetClass.php:116
#, php-format
msgid ""
"If wanting a border around the image, write the style here. %s would make it "
"a black border, 1px wide."
msgstr ""
#: class-lib/ACC_WidgetClass.php:118
msgid "In case there is no excerpt defined, how many sentences are displayed:"
msgstr ""
"En caso de que no haya extracto definido, como cuantas frases se muestran:"
#: class-lib/ACC_WidgetClass.php:119
msgid "Check to display words instead of sentences."
msgstr "Seleccione para mostrar palabras en lugar de oraciones."
#: class-lib/ACC_WidgetClass.php:120
msgid "Check to have each sentense in a new line."
msgstr "Seleccione para tener cada sentencia en una línea nueva."
#: class-lib/ACC_WidgetClass.php:122
msgid ""
"Check to return the excerpt unfiltered (might avoid interferences with other "
"plugins)."
msgstr ""
"Seleccione para retornar el extracto sin filtrar (puede evitar "
"interferencias con otros plugins)."
#: class-lib/ACC_WidgetClass.php:123
msgid ""
"If you want a line between the posts, this is the height in px (if not "
"wanting a line, leave emtpy):"
msgstr ""
"Si usted quiere una línea entre los posts, esta es la altura en píxeles (si "
"no quisiera una línea, deje en blanco)"
#: class-lib/ACC_WidgetClass.php:124
msgid "The color of the line (e.g. #cccccc):"
msgstr "El color de la línea (e.g. #cccccc):"
#: class-lib/ACC_WidgetClass.php:126
#, fuzzy, php-format
msgid ""
"Here you can finally style the widget. Simply type something like%sto get "
"just a gray outline and a padding of 10 px. If you leave that section empty, "
"your theme will style the widget."
msgstr ""
"Aquí usted puede finalmente ver el estilo del widget. Simplemente escriba "
"algo como%1$s%2$sborder-left: 1px dashed;%2$sborder-color: #000000;%3$s"
"%2$spara obtener una línea de puntos negro de la izquierda. Si deja la "
"sección vacía, su tema le dará estilo al widget."
#~ msgid ""
#~ "The Advanced Category Column does, what the Category Column Plugin does; "
#~ "it creates a widget, which you can drag to your sidebar and it will show "
#~ "excerpts of the posts of other categories than showed in the center-"
#~ "column. It just has more options than the the Category Column Plugin. It "
#~ "is tested with WP up to version 3.5 and it might work with versions down "
#~ "to 2.9, but will never be explicitly supported for those. The 'Advanced' "
#~ "means, that you have a couple of more options than in the 'Category "
#~ "Column Plugin'."
#~ msgstr ""
#~ "La Columna Categoría Avanzada hace, lo que hace el Plugin de Columna de "
#~ "Categoría, se crea un widget, que se puede arrastrar a la barra lateral y "
#~ "se mostrarán extractos de los mensajes de otras categorías que se "
#~ "mostraron en la columna del centro. Simplemente tiene más opciones que el "
#~ "Plugin de Columna de Categoría. Se probó con WP hasta la versión 3.5 y "
#~ "que podría funcionar con las versiones hasta la 2.9, pero nunca se probó "
#~ "explícitamente en aquellos. Los menús 'Avanzados' significan, que tiene "
#~ "un par de opciones más que el 'Plugin de Columna de Categoría'."
#~ msgid "Waldemar Stoffel"
#~ msgstr "Waldemar Stoffel"
#~ msgid "http://www.waldemarstoffel.com"
#~ msgstr "http://www.waldemarstoffel.com"

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