HELLO v3!!!
This commit is contained in:
38
spec/app/controllers/aliases_spec.rb
Normal file
38
spec/app/controllers/aliases_spec.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Controller::Aliases do
|
||||
subject(:controller) { described_class.new }
|
||||
let(:target_url) { 'http://ex.lo/' }
|
||||
let(:parsed_options) { rspec_parsed_options(cli_args) }
|
||||
let(:cli_args) { "--url #{target_url}" }
|
||||
|
||||
before do
|
||||
WPScan::Browser.reset
|
||||
described_class.parsed_options = parsed_options
|
||||
end
|
||||
|
||||
describe '#cli_options' do
|
||||
its(:cli_options) { should_not be_empty }
|
||||
its(:cli_options) { should be_a Array }
|
||||
|
||||
it 'contains to correct options' do
|
||||
expect(controller.cli_options.map(&:to_sym)).to eq %i[stealthy]
|
||||
end
|
||||
end
|
||||
|
||||
describe 'parsed_options' do
|
||||
context 'when no --stealthy supplied' do
|
||||
its(:parsed_options) { should eql parsed_options }
|
||||
end
|
||||
|
||||
context 'when --stealthy supplied' do
|
||||
let(:cli_args) { "#{super()} --stealthy" }
|
||||
|
||||
it 'contains the correct options' do
|
||||
expect(controller.parsed_options).to include(
|
||||
random_user_agent: true, detection_mode: :passive, plugins_version_detection: :passive
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
271
spec/app/controllers/core_spec.rb
Normal file
271
spec/app/controllers/core_spec.rb
Normal file
@@ -0,0 +1,271 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Controller::Core do
|
||||
subject(:core) { described_class.new }
|
||||
let(:target_url) { 'http://ex.lo/' }
|
||||
let(:parsed_options) { rspec_parsed_options(cli_args) }
|
||||
let(:cli_args) { "--url #{target_url}" }
|
||||
|
||||
before do
|
||||
WPScan::Browser.reset
|
||||
described_class.reset
|
||||
described_class.parsed_options = parsed_options
|
||||
end
|
||||
|
||||
describe '#cli_options' do
|
||||
its(:cli_options) { should_not be_empty }
|
||||
its(:cli_options) { should be_a Array }
|
||||
|
||||
it 'contains to correct options' do
|
||||
cli_options = core.cli_options
|
||||
expect(cli_options.map(&:to_sym)).to include(:url, :server, :force, :update)
|
||||
|
||||
# Ensures the :url is the first one and is correctly setup
|
||||
expect(cli_options.first.to_sym).to eql :url
|
||||
expect(cli_options.first.required_unless).to match_array %i[update help version]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#load_server_module' do
|
||||
after do
|
||||
expect(core.target).to receive(:server).and_return(@stubbed_server)
|
||||
expect(core.load_server_module).to eql @expected
|
||||
|
||||
[core.target, WPScan::WpItem.new(target_url, core.target)].each do |instance|
|
||||
expect(instance).to respond_to(:directory_listing?)
|
||||
expect(instance).to respond_to(:directory_listing_entries)
|
||||
|
||||
# The below doesn't work, the module would have to be removed from the class
|
||||
# TODO: find a way to test this
|
||||
# expect(instance.server).to eql @expected if instance.is_a? WPScan::WpItem
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no --server supplied' do
|
||||
%i[Apache IIS Nginx].each do |server|
|
||||
it "loads the #{server} module and returns :#{server}" do
|
||||
@stubbed_server = server
|
||||
@expected = server
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when --server' do
|
||||
%i[apache iis nginx].each do |server|
|
||||
context "when #{server}" do
|
||||
let(:cli_args) { "#{super()} --server #{server}" }
|
||||
|
||||
it "loads the #{server.capitalize} module and returns :#{server}" do
|
||||
@stubbed_server = [:Apache, nil, :IIS, :Nginx].sample
|
||||
@expected = server == :iis ? :IIS : server.to_s.camelize.to_sym
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#update_db_required?' do
|
||||
context 'when missing files' do
|
||||
before { expect(core.local_db).to receive(:missing_files?).ordered.and_return(true) }
|
||||
|
||||
context 'when --no-update' do
|
||||
let(:cli_args) { "#{super()} --no-update" }
|
||||
|
||||
it 'raises an error' do
|
||||
expect { core.update_db_required? }. to raise_error(WPScan::MissingDatabaseFile)
|
||||
end
|
||||
end
|
||||
|
||||
context 'otherwise' do
|
||||
its(:update_db_required?) { should eql true }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not missing files' do
|
||||
before { expect(core.local_db).to receive(:missing_files?).ordered.and_return(false) }
|
||||
|
||||
context 'when --update' do
|
||||
let(:cli_args) { "#{super()} --update" }
|
||||
|
||||
its(:update_db_required?) { should eql true }
|
||||
end
|
||||
|
||||
context 'when --no-update' do
|
||||
let(:cli_args) { "#{super()} --no-update" }
|
||||
|
||||
its(:update_db_required?) { should eql false }
|
||||
end
|
||||
|
||||
context 'when user_interation (i.e cli output)' do
|
||||
let(:cli_args) { "#{super()} --format cli" }
|
||||
|
||||
context 'when the db is up-to-date' do
|
||||
before { expect(core.local_db).to receive(:outdated?).and_return(false) }
|
||||
|
||||
its(:update_db_required?) { should eql false }
|
||||
end
|
||||
|
||||
context 'when the db is outdated' do
|
||||
before do
|
||||
expect(core.local_db).to receive(:outdated?).ordered.and_return(true)
|
||||
expect(core.formatter).to receive(:output).with('@notice', hash_including(:msg), 'core').ordered
|
||||
expect($stdout).to receive(:write).ordered # for the print()
|
||||
end
|
||||
|
||||
context 'when a positive answer' do
|
||||
before { expect(Readline).to receive(:readline).and_return('Yes').ordered }
|
||||
|
||||
its(:update_db_required?) { should eql true }
|
||||
end
|
||||
|
||||
context 'when a negative answer' do
|
||||
before { expect(Readline).to receive(:readline).and_return('no').ordered }
|
||||
|
||||
its(:update_db_required?) { should eql false }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no user_interation' do
|
||||
let(:cli_args) { "#{super()} --format json" }
|
||||
|
||||
its(:update_db_required?) { should eql false }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#before_scan' do
|
||||
before do
|
||||
stub_request(:get, target_url)
|
||||
|
||||
expect(core.formatter).to receive(:output).with('banner', hash_including(verbose: nil), 'core')
|
||||
|
||||
expect(core).to receive(:update_db_required?).and_return(false) unless parsed_options[:update]
|
||||
end
|
||||
|
||||
context 'when --update' do
|
||||
before do
|
||||
expect(core.formatter).to receive(:output)
|
||||
.with('db_update_started', hash_including(verbose: nil), 'core').ordered
|
||||
|
||||
expect_any_instance_of(WPScan::DB::Updater).to receive(:update)
|
||||
|
||||
expect(core.formatter).to receive(:output)
|
||||
.with('db_update_finished', hash_including(verbose: nil), 'core').ordered
|
||||
end
|
||||
|
||||
context 'when the --url is not supplied' do
|
||||
let(:cli_args) { '--update' }
|
||||
|
||||
it 'calls the formatter when started and finished to update the db and exit' do
|
||||
expect { core.before_scan }.to raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when --url is supplied' do
|
||||
let(:cli_args) { "#{super()} --update" }
|
||||
|
||||
before do
|
||||
expect(core).to receive(:load_server_module)
|
||||
expect(core.target).to receive(:wordpress?).and_return(true)
|
||||
end
|
||||
|
||||
it 'calls the formatter when started and finished to update the db' do
|
||||
expect { core.before_scan }.to_not raise_error
|
||||
end
|
||||
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::HTTPRedirectError)
|
||||
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?).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?).and_return(false)
|
||||
|
||||
expect { core.before_scan }.to raise_error(WPScan::NotWordPressError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when hosted on wordpress.com' do
|
||||
let(:target_url) { 'http://ex.wordpress.com' }
|
||||
|
||||
before { expect(core).to receive(:load_server_module) }
|
||||
|
||||
it 'raises an error' do
|
||||
expect { core.before_scan }.to raise_error(WPScan::WordPressHostedError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when wordpress' do
|
||||
before do
|
||||
expect(core).to receive(:load_server_module)
|
||||
expect(core.target).to receive(:wordpress?).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)
|
||||
expect(core.target).to receive(:wordpress?).and_return(false)
|
||||
end
|
||||
|
||||
context 'when no --force' do
|
||||
it 'raises an error' do
|
||||
expect { core.before_scan }.to raise_error(WPScan::NotWordPressError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when --force' do
|
||||
let(:cli_args) { "#{super()} --force" }
|
||||
|
||||
it 'does not raise any error' do
|
||||
expect { core.before_scan }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
45
spec/app/controllers/custom_directories_spec.rb
Normal file
45
spec/app/controllers/custom_directories_spec.rb
Normal file
@@ -0,0 +1,45 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Controller::CustomDirectories do
|
||||
subject(:controller) { described_class.new }
|
||||
let(:target_url) { 'http://ex.lo/' }
|
||||
let(:parsed_options) { rspec_parsed_options(cli_args) }
|
||||
let(:cli_args) { "--url #{target_url}" }
|
||||
|
||||
before do
|
||||
WPScan::Browser.reset
|
||||
described_class.parsed_options = parsed_options
|
||||
end
|
||||
|
||||
describe '#cli_options' do
|
||||
its(:cli_options) { should_not be_empty }
|
||||
its(:cli_options) { should be_a Array }
|
||||
|
||||
it 'contains to correct options' do
|
||||
expect(controller.cli_options.map(&:to_sym)).to eq %i[wp_content_dir wp_plugins_dir]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#before_scan' do
|
||||
context 'when the content_dir is not found and not supply' do
|
||||
before { expect(controller.target).to receive(:content_dir) }
|
||||
|
||||
let(:exception) do
|
||||
'Unable to identify the wp-content dir, please supply it with --wp-content-dir'
|
||||
end
|
||||
|
||||
it 'raises an exception' do
|
||||
expect { controller.before_scan }.to raise_error(exception)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when content_dir found/supplied' do
|
||||
let(:cli_args) { "#{super()} --wp-content-dir wp-content" }
|
||||
|
||||
it 'does not raise any error' do
|
||||
expect { controller.before_scan }.to_not raise_error
|
||||
expect(controller.target.content_dir).to eq parsed_options[:wp_content_dir]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
180
spec/app/controllers/enumeration_spec.rb
Normal file
180
spec/app/controllers/enumeration_spec.rb
Normal file
@@ -0,0 +1,180 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Controller::Enumeration do
|
||||
subject(:controller) { described_class.new }
|
||||
let(:target_url) { 'http://wp.lab/' }
|
||||
let(:parsed_options) { rspec_parsed_options(cli_args) }
|
||||
let(:cli_args) { "--url #{target_url}" }
|
||||
|
||||
before do
|
||||
WPScan::Browser.reset
|
||||
|
||||
## For the --passwords options
|
||||
allow_any_instance_of(OptParseValidator::OptPath).to receive(:check_file)
|
||||
|
||||
described_class.parsed_options = parsed_options
|
||||
end
|
||||
|
||||
describe '#enum_message' do
|
||||
after { expect(controller.enum_message(type)).to eql @expected }
|
||||
|
||||
context 'when type argument is incorrect' do
|
||||
let(:type) { 'spec' }
|
||||
|
||||
it 'returns nil' do
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
%w[plugins themes].each do |t|
|
||||
context "type = #{t}" do
|
||||
let(:type) { t }
|
||||
|
||||
context 'when vulnerable' do
|
||||
let(:cli_args) { "#{super()} -e v#{type[0]}" }
|
||||
|
||||
it 'returns the expected string' do
|
||||
@expected = "Enumerating Vulnerable #{type.capitalize}"
|
||||
end
|
||||
end
|
||||
|
||||
context 'when all' do
|
||||
let(:cli_args) { "#{super()} -e a#{type[0]}" }
|
||||
|
||||
it 'returns the expected string' do
|
||||
@expected = "Enumerating All #{type.capitalize}"
|
||||
end
|
||||
end
|
||||
|
||||
context 'when most popular' do
|
||||
let(:cli_args) { "#{super()} -e #{type[0]}" }
|
||||
|
||||
it 'returns the expected string' do
|
||||
@expected = "Enumerating Most Popular #{type.capitalize}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#default_opts' do
|
||||
context 'when no --enumerate' do
|
||||
it 'contains the correct version_detection' do
|
||||
expect(controller.default_opts('plugins')[:version_detection]).to include(mode: :mixed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#cli_options' do
|
||||
it 'contains the correct options' do
|
||||
expect(controller.cli_options.map(&:to_sym)).to eql(
|
||||
%i[enumerate exclude_content_based
|
||||
plugins_list plugins_detection plugins_version_all plugins_version_detection
|
||||
themes_list themes_detection themes_version_all themes_version_detection
|
||||
timthumbs_list timthumbs_detection
|
||||
config_backups_list config_backups_detection
|
||||
db_exports_list db_exports_detection
|
||||
medias_detection
|
||||
users_list users_detection]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#enum_users' do
|
||||
before { expect(controller.formatter).to receive(:output).twice }
|
||||
after { controller.enum_users }
|
||||
|
||||
context 'when --enumerate has been supplied' do
|
||||
let(:cli_args) { "#{super()} -e u1-10" }
|
||||
|
||||
it 'calls the target.users with the correct range' do
|
||||
expect(controller.target).to receive(:users).with(hash_including(range: (1..10)))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when --passwords supplied but no --username or --usernames' do
|
||||
let(:cli_args) { "#{super()} --passwords some-file.txt" }
|
||||
|
||||
it 'calls the target.users with the default range' do
|
||||
expect(controller.target).to receive(:users).with(hash_including(range: (1..10)))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#before_scan' do
|
||||
it 'creates the Dynamic Finders' do
|
||||
expect(WPScan::DB::DynamicFinders::Plugin).to receive(:create_versions_finders)
|
||||
expect(WPScan::DB::DynamicFinders::Theme).to receive(:create_versions_finders)
|
||||
|
||||
controller.before_scan
|
||||
end
|
||||
end
|
||||
|
||||
describe '#run' do
|
||||
context 'when no :enumerate' do
|
||||
before do
|
||||
expect(controller).to receive(:enum_plugins)
|
||||
expect(controller).to receive(:enum_config_backups)
|
||||
|
||||
expect(parsed_options[:plugins_detection]).to eql :passive
|
||||
end
|
||||
|
||||
it 'calls enum_plugins and enum_config_backups' do
|
||||
controller.run
|
||||
end
|
||||
|
||||
context 'when --passwords supplied but no --username or --usernames' do
|
||||
let(:cli_args) { "#{super()} --passwords some-file.txt" }
|
||||
|
||||
it 'calls the enum_users' do
|
||||
expect(controller).to receive(:enum_users)
|
||||
controller.run
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :enumerate' do
|
||||
after { controller.run }
|
||||
|
||||
context 'when no option supplied' do
|
||||
let(:cli_args) { "#{super()} -e" }
|
||||
|
||||
it 'calls the correct enum methods' do
|
||||
%i[plugins themes timthumbs config_backups db_exports users medias].each do |option|
|
||||
expect(controller).to receive("enum_#{option}".to_sym)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%i[p ap vp].each do |option|
|
||||
context "when #{option}" do
|
||||
let(:cli_args) { "#{super()} -e #{option}" }
|
||||
|
||||
it 'calls the #enum_plugins' do
|
||||
expect(controller).to receive(:enum_plugins)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%i[t at vt].each do |option|
|
||||
context option.to_s do
|
||||
let(:cli_args) { "#{super()} -e #{option}" }
|
||||
|
||||
it 'calls the #enum_themes' do
|
||||
expect(controller).to receive(:enum_themes)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
{ timthumbs: 'tt', config_backups: 'cb', db_exports: 'dbe', medias: 'm', users: 'u' }.each do |option, shortname|
|
||||
context "when #{option}" do
|
||||
let(:cli_args) { "#{super()} -e #{shortname}" }
|
||||
|
||||
it "calls the ##{option}" do
|
||||
expect(controller).to receive("enum_#{option}".to_sym)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
169
spec/app/controllers/password_attack_spec.rb
Normal file
169
spec/app/controllers/password_attack_spec.rb
Normal file
@@ -0,0 +1,169 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Controller::PasswordAttack do
|
||||
subject(:controller) { described_class.new }
|
||||
let(:target_url) { 'http://ex.lo/' }
|
||||
let(:parsed_options) { rspec_parsed_options(cli_args) }
|
||||
let(:cli_args) { "--url #{target_url}" }
|
||||
|
||||
before do
|
||||
WPScan::Browser.reset
|
||||
described_class.parsed_options = parsed_options
|
||||
end
|
||||
|
||||
describe '#cli_options' do
|
||||
its(:cli_options) { should_not be_empty }
|
||||
its(:cli_options) { should be_a Array }
|
||||
|
||||
it 'contains to correct options' do
|
||||
expect(controller.cli_options.map(&:to_sym))
|
||||
.to eq(%i[passwords usernames multicall_max_passwords password_attack])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#users' do
|
||||
context 'when no --usernames' do
|
||||
it 'calles target.users' do
|
||||
expect(controller.target).to receive(:users)
|
||||
controller.users
|
||||
end
|
||||
end
|
||||
|
||||
context 'when --usernames' do
|
||||
let(:cli_args) { "#{super()} --usernames admin,editor" }
|
||||
|
||||
it 'returns an array with the users' do
|
||||
expected = %w[admin editor].reduce([]) do |a, e|
|
||||
a << CMSScanner::User.new(e)
|
||||
end
|
||||
|
||||
expect(controller.users).to eql expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#passwords' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#run' do
|
||||
context 'when no --passwords is supplied' do
|
||||
it 'does not run the attacker' do
|
||||
expect(controller.run).to eql nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#attacker' do
|
||||
context 'when --password-attack provided' do
|
||||
let(:cli_args) { "#{super()} --password-attack #{attack}" }
|
||||
|
||||
context 'when wp-login' do
|
||||
let(:attack) { 'wp-login' }
|
||||
|
||||
it 'returns the correct object' do
|
||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin
|
||||
expect(controller.attacker.target).to be_a WPScan::Target
|
||||
end
|
||||
end
|
||||
|
||||
context 'when xmlrpc' do
|
||||
before do
|
||||
expect(controller.target).to receive(:xmlrpc).and_return(WPScan::XMLRPC.new("#{target_url}/xmlrpc.php"))
|
||||
end
|
||||
|
||||
context 'when single xmlrpc' do
|
||||
let(:attack) { 'xmlrpc' }
|
||||
|
||||
it 'returns the correct object' do
|
||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
|
||||
expect(controller.attacker.target).to be_a WPScan::XMLRPC
|
||||
end
|
||||
end
|
||||
|
||||
context 'when xmlrpc-multicall' do
|
||||
let(:attack) { 'xmlrpc-multicall' }
|
||||
|
||||
it 'returns the correct object' do
|
||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPCMulticall
|
||||
expect(controller.attacker.target).to be_a WPScan::XMLRPC
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when automatic detection' do
|
||||
before { expect(controller.target).to receive(:xmlrpc).and_return(xmlrpc) }
|
||||
|
||||
context 'when xmlrpc not found' do
|
||||
let(:xmlrpc) { nil }
|
||||
|
||||
it 'returns the WpLogin' do
|
||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin
|
||||
expect(controller.attacker.target).to be_a WPScan::Target
|
||||
end
|
||||
end
|
||||
|
||||
context 'when xmlrpc not enabled' do
|
||||
let(:xmlrpc) { WPScan::XMLRPC.new("#{target_url}/xmlrpc.php") }
|
||||
|
||||
it 'returns the WpLogin' do
|
||||
expect(xmlrpc).to receive(:enabled?).and_return(false)
|
||||
|
||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin
|
||||
expect(controller.attacker.target).to be_a WPScan::Target
|
||||
end
|
||||
end
|
||||
|
||||
context 'when xmlrpc enabled' do
|
||||
let(:xmlrpc) { WPScan::XMLRPC.new("#{target_url}/xmlrpc.php") }
|
||||
|
||||
before { expect(xmlrpc).to receive(:enabled?).and_return(true) }
|
||||
|
||||
context 'when wp.getUsersBlogs methods not available' do
|
||||
it 'returns the WpLogin' do
|
||||
expect(xmlrpc).to receive(:available_methods).and_return(%w[m1 m2])
|
||||
|
||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin
|
||||
expect(controller.attacker.target).to be_a WPScan::Target
|
||||
end
|
||||
end
|
||||
|
||||
context 'when wp.getUsersBlogs method evailable' do
|
||||
before { expect(xmlrpc).to receive(:available_methods).and_return(%w[wp.getUsersBlogs m2]) }
|
||||
|
||||
context 'when WP version not found' do
|
||||
it 'returns the XMLRPC' do
|
||||
expect(controller.target).to receive(:wp_version).and_return(false)
|
||||
|
||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
|
||||
expect(controller.attacker.target).to be_a WPScan::XMLRPC
|
||||
end
|
||||
end
|
||||
|
||||
context 'when WP version found' do
|
||||
before { expect(controller.target).to receive(:wp_version).and_return(wp_version) }
|
||||
|
||||
context 'when WP < 4.4' do
|
||||
let(:wp_version) { WPScan::WpVersion.new('3.8.1') }
|
||||
|
||||
it 'returns the XMLRPCMulticall' do
|
||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPCMulticall
|
||||
expect(controller.attacker.target).to be_a WPScan::XMLRPC
|
||||
end
|
||||
end
|
||||
|
||||
context 'when WP >= 4.4' do
|
||||
let(:wp_version) { WPScan::WpVersion.new('4.4') }
|
||||
|
||||
it 'returns the XMLRPC' do
|
||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
|
||||
expect(controller.attacker.target).to be_a WPScan::XMLRPC
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
85
spec/app/controllers/wp_version_spec.rb
Normal file
85
spec/app/controllers/wp_version_spec.rb
Normal file
@@ -0,0 +1,85 @@
|
||||
require 'spec_helper'
|
||||
|
||||
def it_calls_the_formatter_with_the_correct_parameter(version)
|
||||
it 'calls the formatter with the correct parameter' do
|
||||
expect(controller.formatter).to receive(:output)
|
||||
.with('version', hash_including(version: version), 'wp_version')
|
||||
end
|
||||
end
|
||||
|
||||
describe WPScan::Finders::WpVersionFinders do
|
||||
subject(:finders) { described_class.new }
|
||||
|
||||
describe 'filter_findings' do
|
||||
context 'when super returns false (nothing found)' do
|
||||
before do
|
||||
expect_any_instance_of(WPScan::Finders::UniqueFinders).to receive(:filter_findings).and_return(false)
|
||||
end
|
||||
|
||||
its(:filter_findings) { should be false }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe WPScan::Controller::WpVersion do
|
||||
subject(:controller) { described_class.new }
|
||||
let(:target_url) { 'http://ex.lo/' }
|
||||
let(:parsed_options) { rspec_parsed_options(cli_args) }
|
||||
let(:cli_args) { "--url #{target_url}" }
|
||||
|
||||
before do
|
||||
WPScan::Browser.reset
|
||||
described_class.parsed_options = parsed_options
|
||||
end
|
||||
|
||||
describe '#cli_options' do
|
||||
its(:cli_options) { should_not be_empty }
|
||||
its(:cli_options) { should be_a Array }
|
||||
|
||||
it 'contains to correct options' do
|
||||
expect(controller.cli_options.map(&:to_sym)).to eq %i[wp_version_all wp_version_detection]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#run' do
|
||||
before do
|
||||
expect(controller.target).to receive(:wp_version)
|
||||
.with(
|
||||
hash_including(
|
||||
mode: parsed_options[:wp_version_detection] || parsed_options[:detection_mode],
|
||||
confidence_threshold: parsed_options[:wp_version_all] ? 0 : 100
|
||||
)
|
||||
).and_return(stubbed)
|
||||
end
|
||||
|
||||
after { controller.run }
|
||||
|
||||
%i[mixed passive aggressive].each do |mode|
|
||||
context "when --detection-mode #{mode}" do
|
||||
let(:cli_args) { "#{super()} --detection-mode #{mode}" }
|
||||
|
||||
[WPScan::WpVersion.new('4.0')].each do |version|
|
||||
context "when version = #{version}" do
|
||||
let(:stubbed) { version }
|
||||
|
||||
it_calls_the_formatter_with_the_correct_parameter(version)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when --wp-version-all supplied' do
|
||||
let(:cli_args) { "#{super()} --wp-version-all" }
|
||||
let(:stubbed) { WPScan::WpVersion.new('3.9.1') }
|
||||
|
||||
it_calls_the_formatter_with_the_correct_parameter(WPScan::WpVersion.new('3.9.1'))
|
||||
end
|
||||
|
||||
context 'when --wp-version-detection mode supplied' do
|
||||
let(:cli_args) { "#{super()} --detection-mode mixed --wp-version-detection passive" }
|
||||
let(:stubbed) { WPScan::WpVersion.new('4.4') }
|
||||
|
||||
it_calls_the_formatter_with_the_correct_parameter(WPScan::WpVersion.new('4.4'))
|
||||
end
|
||||
end
|
||||
end
|
||||
52
spec/app/finders/config_backups/known_filenames_spec.rb
Normal file
52
spec/app/finders/config_backups/known_filenames_spec.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::ConfigBackups::KnownFilenames do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'config_backups') }
|
||||
let(:opts) { { list: File.join(WPScan::DB_DIR, 'config_backups.txt') } }
|
||||
|
||||
describe '#aggressive' do
|
||||
before do
|
||||
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
|
||||
expect(target).to receive(:homepage_or_404?).at_least(1).and_return(false)
|
||||
|
||||
finder.potential_urls(opts).each_key do |url|
|
||||
stub_request(:get, url).to_return(status: 404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when all files are 404s' do
|
||||
it 'returns an empty array' do
|
||||
expect(finder.aggressive(opts)).to eql []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when some files exist' do
|
||||
let(:files) { ['%23wp-config.php%23', 'wp-config.bak'] }
|
||||
let(:config_backup) { File.read(File.join(fixtures, 'wp-config.php')) }
|
||||
|
||||
before do
|
||||
files.each do |file|
|
||||
stub_request(:get, "#{url}#{file}").to_return(body: config_backup)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the expected Array<ConfigBackup>' do
|
||||
expected = []
|
||||
|
||||
files.each do |file|
|
||||
url = "#{target.url}#{file}"
|
||||
expected << WPScan::ConfigBackup.new(
|
||||
url,
|
||||
confidence: 100,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
end
|
||||
|
||||
expect(finder.aggressive(opts)).to eql expected
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
13
spec/app/finders/config_backups_spec.rb
Normal file
13
spec/app/finders/config_backups_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::ConfigBackups::Base do
|
||||
subject(:config_backups) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
|
||||
describe '#finders' do
|
||||
it 'contains the expected finders' do
|
||||
expect(config_backups.finders.map { |f| f.class.to_s.demodulize }).to eq %w[KnownFilenames]
|
||||
end
|
||||
end
|
||||
end
|
||||
69
spec/app/finders/db_exports/known_locations_spec.rb
Normal file
69
spec/app/finders/db_exports/known_locations_spec.rb
Normal file
@@ -0,0 +1,69 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::DbExports::KnownLocations do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/aa/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'db_exports') }
|
||||
let(:opts) { { list: File.join(WPScan::DB_DIR, 'db_exports.txt') } }
|
||||
|
||||
describe '#potential_urls' do
|
||||
before do
|
||||
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
|
||||
end
|
||||
|
||||
it 'replace {domain_name} by its value' do
|
||||
expect(finder.potential_urls(opts).keys).to eql %w[
|
||||
http://ex.lo/aa/ex.sql
|
||||
http://ex.lo/aa/wordpress.sql
|
||||
http://ex.lo/aa/backup/ex.zip
|
||||
http://ex.lo/aa/backup/mysql.sql
|
||||
http://ex.lo/aa/backups/ex.sql.gz
|
||||
http://ex.lo/aa/backups/db_backup.sql
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#aggressive' do
|
||||
before do
|
||||
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
|
||||
expect(target).to receive(:homepage_or_404?).at_least(1).and_return(false)
|
||||
|
||||
finder.potential_urls(opts).each_key do |url|
|
||||
stub_request(:get, url).to_return(status: 404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when all files are 404s' do
|
||||
it 'returns an empty array' do
|
||||
expect(finder.aggressive(opts)).to eql []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when some files exist' do
|
||||
let(:files) { %w[ex.sql backups/db_backup.sql] }
|
||||
let(:db_export) { File.read(File.join(fixtures, 'dump.sql')) }
|
||||
|
||||
before do
|
||||
files.each do |file|
|
||||
stub_request(:get, "#{url}#{file}").to_return(body: db_export)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the expected Array<DbExport>' do
|
||||
expected = []
|
||||
|
||||
files.each do |file|
|
||||
url = "#{target.url}#{file}"
|
||||
expected << WPScan::DbExport.new(
|
||||
url,
|
||||
confidence: 100,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
end
|
||||
|
||||
expect(finder.aggressive(opts)).to eql expected
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
13
spec/app/finders/db_exports_spec.rb
Normal file
13
spec/app/finders/db_exports_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::DbExports::Base do
|
||||
subject(:db_exports) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
|
||||
describe '#finders' do
|
||||
it 'contains the expected finders' do
|
||||
expect(db_exports.finders.map { |f| f.class.to_s.demodulize }).to eq %w[KnownLocations]
|
||||
end
|
||||
end
|
||||
end
|
||||
64
spec/app/finders/interesting_findings/backup_db_spec.rb
Normal file
64
spec/app/finders/interesting_findings/backup_db_spec.rb
Normal file
@@ -0,0 +1,64 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::BackupDB do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'backup_db') }
|
||||
let(:wp_content) { 'wp-content' }
|
||||
let(:dir_url) { target.url("#{wp_content}/backup-db/") }
|
||||
|
||||
before { expect(target).to receive(:content_dir).at_least(1).and_return(wp_content) }
|
||||
|
||||
describe '#aggressive' do
|
||||
before { stub_request(:get, dir_url).to_return(status: status, body: body) }
|
||||
|
||||
let(:body) { '' }
|
||||
|
||||
context 'when not a 200 or 403' do
|
||||
let(:status) { 404 }
|
||||
|
||||
its(:aggressive) { should be_nil }
|
||||
end
|
||||
|
||||
context 'when 200 and matching the homepage' do
|
||||
before { expect(target).to receive(:homepage_or_404?).and_return(true) }
|
||||
|
||||
let(:status) { 200 }
|
||||
|
||||
its(:aggressive) { should be_nil }
|
||||
end
|
||||
|
||||
context 'when 200 or 403' do
|
||||
before { expect(target).to receive(:homepage_or_404?).and_return(false) }
|
||||
|
||||
let(:status) { 200 }
|
||||
|
||||
after do
|
||||
found = finder.aggressive
|
||||
|
||||
expect(found).to eql WPScan::InterestingFinding.new(
|
||||
dir_url,
|
||||
confidence: 70,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
|
||||
expect(found.interesting_entries).to eq @expected_entries
|
||||
end
|
||||
|
||||
context 'when no directory listing' do
|
||||
it 'returns an empty interesting_findings attribute' do
|
||||
@expected_entries = []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when directory listing enabled' do
|
||||
let(:body) { File.read(File.join(fixtures, 'dir_listing.html')) }
|
||||
|
||||
it 'returns the expected interesting_findings attribute' do
|
||||
@expected_entries = %w[sqldump.sql test.txt]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
34
spec/app/finders/interesting_findings/debug_log_spec.rb
Normal file
34
spec/app/finders/interesting_findings/debug_log_spec.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::DebugLog do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'debug_log') }
|
||||
let(:wp_content) { 'wp-content' }
|
||||
let(:log_url) { target.url("#{wp_content}/debug.log") }
|
||||
|
||||
before { expect(target).to receive(:content_dir).at_least(1).and_return(wp_content) }
|
||||
|
||||
describe '#aggressive' do
|
||||
before { stub_request(:get, log_url).to_return(body: body) }
|
||||
|
||||
context 'when empty file' do
|
||||
let(:body) { '' }
|
||||
|
||||
its(:aggressive) { should be_nil }
|
||||
end
|
||||
|
||||
context 'when a log file' do
|
||||
let(:body) { File.read(File.join(fixtures, 'debug.log')) }
|
||||
|
||||
it 'returns the InterestingFinding' do
|
||||
expect(finder.aggressive).to eql WPScan::InterestingFinding.new(
|
||||
log_url,
|
||||
confidence: 100,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,35 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::DuplicatorInstallerLog do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'duplicator_installer_log') }
|
||||
let(:filename) { 'installer-log.txt' }
|
||||
let(:log_url) { target.url(filename) }
|
||||
|
||||
describe '#aggressive' do
|
||||
before do
|
||||
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
|
||||
stub_request(:get, log_url).to_return(body: body)
|
||||
end
|
||||
|
||||
context 'when the body does not match' do
|
||||
let(:body) { '' }
|
||||
|
||||
its(:aggressive) { should be_nil }
|
||||
end
|
||||
|
||||
context 'when the body matches' do
|
||||
let(:body) { File.read(File.join(fixtures, filename)) }
|
||||
|
||||
it 'returns the InterestingFinding' do
|
||||
expect(finder.aggressive).to eql WPScan::InterestingFinding.new(
|
||||
log_url,
|
||||
confidence: 100,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::EmergencyPwdResetScript do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'emergency_pwd_reset_script') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,37 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::FullPathDisclosure do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'fpd') }
|
||||
let(:file_url) { target.url('wp-includes/rss-functions.php') }
|
||||
|
||||
describe '#aggressive' do
|
||||
before do
|
||||
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
|
||||
stub_request(:get, file_url).to_return(body: body)
|
||||
end
|
||||
|
||||
context 'when empty file' do
|
||||
let(:body) { '' }
|
||||
|
||||
its(:aggressive) { should be_nil }
|
||||
end
|
||||
|
||||
context 'when a log file' do
|
||||
let(:body) { File.read(File.join(fixtures, 'rss_functions.php')) }
|
||||
|
||||
it 'returns the InterestingFinding' do
|
||||
found = finder.aggressive
|
||||
|
||||
expect(found).to eql WPScan::InterestingFinding.new(
|
||||
file_url,
|
||||
confidence: 100,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
expect(found.interesting_entries).to eql %w[/blog/wp-includes/rss-functions.php]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
16
spec/app/finders/interesting_findings/mu_plugins_spec.rb
Normal file
16
spec/app/finders/interesting_findings/mu_plugins_spec.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::MuPlugins do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'mu_plugins') }
|
||||
|
||||
describe '#passive' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
12
spec/app/finders/interesting_findings/multisite_spec.rb
Normal file
12
spec/app/finders/interesting_findings/multisite_spec.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::Multisite do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'multisite') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
46
spec/app/finders/interesting_findings/readme_spec.rb
Normal file
46
spec/app/finders/interesting_findings/readme_spec.rb
Normal file
@@ -0,0 +1,46 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::Readme do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'readme') }
|
||||
|
||||
describe '#aggressive' do
|
||||
before do
|
||||
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
|
||||
|
||||
finder.potential_files.each do |file|
|
||||
stub_request(:get, target.url(file)).to_return(status: 404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no file present' do
|
||||
its(:aggressive) { should be_nil }
|
||||
end
|
||||
|
||||
# TODO: case when multiple files are present ? (should return only the first one found)
|
||||
context 'when a file exists' do
|
||||
let(:file) { finder.potential_files.sample }
|
||||
let(:readme) { File.read(File.join(fixtures, 'readme-3.9.2.html')) }
|
||||
|
||||
before { stub_request(:get, target.url(file)).to_return(body: readme) }
|
||||
|
||||
it 'returns the expected InterestingFinding' do
|
||||
expected = WPScan::InterestingFinding.new(
|
||||
target.url(file),
|
||||
confidence: 100,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
|
||||
expect(finder.aggressive).to eql expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#potential_files' do
|
||||
it 'does not contain duplicates' do
|
||||
expect(finder.potential_files.flatten.uniq.length).to eql finder.potential_files.length
|
||||
end
|
||||
end
|
||||
end
|
||||
12
spec/app/finders/interesting_findings/registration_spec.rb
Normal file
12
spec/app/finders/interesting_findings/registration_spec.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::Registration do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'registration') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
12
spec/app/finders/interesting_findings/tmm_db_migrate_spec.rb
Normal file
12
spec/app/finders/interesting_findings/tmm_db_migrate_spec.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::TmmDbMigrate do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'tmm_db_migrate') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::UploadDirectoryListing do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'upload_directory_listing') }
|
||||
let(:wp_content) { 'wp-content' }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,50 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::UploadSQLDump do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'upload_sql_dump') }
|
||||
let(:wp_content) { 'wp-content' }
|
||||
|
||||
describe '#aggressive' do
|
||||
before { expect(target).to receive(:content_dir).at_least(1).and_return(wp_content) }
|
||||
|
||||
after { expect(finder.aggressive).to eql @expected }
|
||||
|
||||
context 'when not a 200' do
|
||||
it 'returns nil' do
|
||||
stub_request(:get, finder.dump_url).to_return(status: 404)
|
||||
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a 200' do
|
||||
before do
|
||||
stub_request(:get, finder.dump_url)
|
||||
.to_return(status: 200, body: File.read(File.join(fixtures, fixture)))
|
||||
end
|
||||
|
||||
context 'when the body does not match a SQL dump' do
|
||||
let(:fixture) { 'not_sql.txt' }
|
||||
|
||||
it 'returns nil' do
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the body matches a SQL dump' do
|
||||
let(:fixture) { 'dump.sql' }
|
||||
|
||||
it 'returns the interesting findings' do
|
||||
@expected = WPScan::InterestingFinding.new(
|
||||
finder.dump_url,
|
||||
confidence: 100,
|
||||
found_by: described_class::DIRECT_ACCESS
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
21
spec/app/finders/interesting_findings_spec.rb
Normal file
21
spec/app/finders/interesting_findings_spec.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::InterestingFindings::Base do
|
||||
subject(:files) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
|
||||
describe '#finders' do
|
||||
let(:expected) do
|
||||
%w[
|
||||
Readme DebugLog FullPathDisclosure
|
||||
Multisite MuPlugins Registration UploadDirectoryListing TmmDbMigrate
|
||||
UploadSQLDump
|
||||
]
|
||||
end
|
||||
|
||||
it 'contains the expected finders' do
|
||||
expect(files.finders.map { |f| f.class.to_s.demodulize }).to include(*expected)
|
||||
end
|
||||
end
|
||||
end
|
||||
58
spec/app/finders/main_theme/css_style_spec.rb
Normal file
58
spec/app/finders/main_theme/css_style_spec.rb
Normal file
@@ -0,0 +1,58 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::MainTheme::CssStyle 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) { File.join(FINDERS_FIXTURES, 'main_theme', 'css_style') }
|
||||
|
||||
describe '#passive' do
|
||||
after do
|
||||
stub_request(:get, url).to_return(body: File.read(File.join(fixtures, fixture)))
|
||||
expect(finder.passive).to eql @expected
|
||||
end
|
||||
|
||||
context 'when no in scope style' do
|
||||
let(:fixture) { 'no_in_scope_style.html' }
|
||||
|
||||
it 'returns nil' do
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when in scope style' do
|
||||
before do
|
||||
expect(target).to receive(:content_dir).at_least(1).and_return('wp-content')
|
||||
stub_request(:get, /.*.css/)
|
||||
end
|
||||
|
||||
context 'when in a link href' do
|
||||
let(:fixture) { 'link_href.html' }
|
||||
|
||||
it 'returns the expected theme' do
|
||||
@expected = WPScan::Theme.new(
|
||||
'twentyfifteen',
|
||||
target,
|
||||
found_by: 'Css Style (Passive Detection)',
|
||||
confidence: 70,
|
||||
style_url: 'http://wp.lab/wp-content/themes/twentyfifteen/style.css?ver=4.1.1'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when in the style code' do
|
||||
let(:fixture) { 'style_code.html' }
|
||||
|
||||
it 'returns the expected theme' do
|
||||
@expected = WPScan::Theme.new(
|
||||
'custom',
|
||||
target,
|
||||
found_by: 'Css Style (Passive Detection)',
|
||||
confidence: 70,
|
||||
style_url: 'http://wp.lab/wp-content/themes/custom/style.css'
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
35
spec/app/finders/main_theme/urls_in_homepage_spec.rb
Normal file
35
spec/app/finders/main_theme/urls_in_homepage_spec.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::MainTheme::UrlsInHomepage do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'main_theme', 'urls_in_homepage') }
|
||||
|
||||
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
|
||||
let(:type) { 'themes' }
|
||||
let(:uniq_links) { false }
|
||||
let(:uniq_codes) { false }
|
||||
let(:expected_from_links) { %w[twentyfifteen twentyfifteen twentyfifteen yolo] }
|
||||
let(:expected_from_codes) { %w[test yolo] }
|
||||
end
|
||||
|
||||
describe '#passive' do
|
||||
before do
|
||||
stub_request(:get, /.*.css/)
|
||||
stub_request(:get, target.url).to_return(body: File.read(File.join(fixtures, 'found.html')))
|
||||
end
|
||||
|
||||
it 'returns the expected Themes' do
|
||||
@expected = []
|
||||
|
||||
{ 'twentyfifteen' => 6, 'yolo' => 4, 'test' => 2 }.each do |slug, confidence|
|
||||
@expected << WPScan::Theme.new(
|
||||
slug, target, found_by: 'Urls In Homepage (Passive Detection)', confidence: confidence
|
||||
)
|
||||
end
|
||||
|
||||
expect(finder.passive).to eql @expected
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::MainTheme::WooFrameworkMetaGenerator 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) { File.join(FINDERS_FIXTURES, 'main_theme', 'woo_framework_meta_generator') }
|
||||
|
||||
describe '#passive' do
|
||||
after do
|
||||
stub_request(:get, url).to_return(body: File.read(File.join(fixtures, @file)))
|
||||
|
||||
expect(finder.passive).to eql @expected
|
||||
end
|
||||
|
||||
context 'when no Woo generator' do
|
||||
it 'returns nil' do
|
||||
@file = 'no_woo_generator.html'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when Woo generator' do
|
||||
before do
|
||||
expect(target).to receive(:content_dir).at_least(1).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::Theme.new(
|
||||
'Merchant', target,
|
||||
found_by: 'Woo Framework Meta Generator (Passive Detection)',
|
||||
confidence: 80
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
14
spec/app/finders/main_theme_spec.rb
Normal file
14
spec/app/finders/main_theme_spec.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::MainTheme::Base do
|
||||
subject(:main_theme) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
|
||||
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]
|
||||
end
|
||||
end
|
||||
end
|
||||
21
spec/app/finders/medias/attachment_brute_forcing_spec.rb
Normal file
21
spec/app/finders/medias/attachment_brute_forcing_spec.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Medias::AttachmentBruteForcing do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'medias', 'attachment_brute_forcing') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#target_urls' do
|
||||
it 'returns the expected urls' do
|
||||
expect(finder.target_urls(range: (1..2))).to eql(
|
||||
url + '?attachment_id=1' => 1,
|
||||
url + '?attachment_id=2' => 2
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
13
spec/app/finders/medias_spec.rb
Normal file
13
spec/app/finders/medias_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Medias::Base do
|
||||
subject(:media) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
|
||||
describe '#finders' do
|
||||
it 'contains the expected finders' do
|
||||
expect(media.finders.map { |f| f.class.to_s.demodulize }).to eq %w[AttachmentBruteForcing]
|
||||
end
|
||||
end
|
||||
end
|
||||
116
spec/app/finders/plugin_version/readme_spec.rb
Normal file
116
spec/app/finders/plugin_version/readme_spec.rb
Normal file
@@ -0,0 +1,116 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::PluginVersion::Readme do
|
||||
subject(:finder) { described_class.new(plugin) }
|
||||
let(:plugin) { WPScan::Plugin.new('spec', target) }
|
||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'plugin_version', 'readme') }
|
||||
|
||||
def version(number, found_by, confidence)
|
||||
WPScan::Version.new(
|
||||
number,
|
||||
found_by: format('Readme - %s (Aggressive Detection)', found_by),
|
||||
confidence: confidence,
|
||||
interesting_entries: [readme_url]
|
||||
)
|
||||
end
|
||||
|
||||
def stable_tag(number)
|
||||
version(number, 'Stable Tag', 80)
|
||||
end
|
||||
|
||||
def changelog_section(number)
|
||||
version(number, 'ChangeLog Section', 50)
|
||||
end
|
||||
|
||||
describe '#aggressive' do
|
||||
before { expect(target).to receive(:content_dir).and_return('wp-content') }
|
||||
|
||||
after do
|
||||
stub_request(:get, /.*/).to_return(status: 404)
|
||||
stub_request(:get, readme_url).to_return(body: File.read(File.join(fixtures, @file)))
|
||||
|
||||
expect(finder.aggressive).to eql @expected
|
||||
end
|
||||
|
||||
let(:readme_url) { plugin.url(WPScan::WpItem::READMES.sample) }
|
||||
|
||||
context 'when no version' do
|
||||
it 'returns nil' do
|
||||
@file = 'no_version.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the stable tag does not contain numbers' do
|
||||
it 'returns nil' do
|
||||
@file = 'aa-health-calculator.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when empty changelog section' do
|
||||
it 'returns nil' do
|
||||
@file = 'all-in-one-facebook.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no changelog section' do
|
||||
it 'returns nil' do
|
||||
@file = 'blog-reordering.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when leaked from the stable tag' do
|
||||
it 'returns the expected versions' do
|
||||
@file = 'simple-login-lockdown-0.4.txt'
|
||||
@expected = [stable_tag('0.4'), changelog_section('04')]
|
||||
end
|
||||
end
|
||||
|
||||
context 'when leaked from the version' do
|
||||
it 'returns it' do
|
||||
@file = 'wp-photo-plus-5.1.15.txt'
|
||||
@expected = [stable_tag('5.1.15')]
|
||||
end
|
||||
end
|
||||
|
||||
context 'when version is in a release date format' do
|
||||
it 'detects and returns it' do
|
||||
@file = 's2member.txt'
|
||||
@expected = [stable_tag('141007')]
|
||||
end
|
||||
end
|
||||
|
||||
context 'when version contains letters' do
|
||||
it 'returns it' do
|
||||
@file = 'beta1.txt'
|
||||
@expected = [stable_tag('2.0.0-beta1')]
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
{
|
||||
'changelog_version' => '1.3',
|
||||
'wp_polls' => '2.64',
|
||||
'nextgen_gallery' => '2.0.66.33',
|
||||
'wp_user_frontend' => '1.2.3',
|
||||
'my_calendar' => '2.1.5',
|
||||
'nextgen_gallery_2' => '1.9.13',
|
||||
'advanced-most-recent-posts-mod' => '1.6.5.2',
|
||||
'a-lead-capture-contact-form-and-tab-button-by-awebvoicecom' => '3.1',
|
||||
'backup-scheduler' => '1.5.9',
|
||||
'release_date_slash' => '1.0.4'
|
||||
}. each do |file, version_number|
|
||||
context "whith #{file}.txt" do
|
||||
it 'returns the expected version' do
|
||||
@file = "#{file}.txt"
|
||||
@expected = [changelog_section(version_number)]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
46
spec/app/finders/plugin_version_spec.rb
Normal file
46
spec/app/finders/plugin_version_spec.rb
Normal file
@@ -0,0 +1,46 @@
|
||||
require 'spec_helper'
|
||||
|
||||
# If this file is tested alone (rspec path-to-this-file), then there will be an error about
|
||||
# constants not being intilialized. This is due to the Dynamic Finders.
|
||||
|
||||
describe WPScan::Finders::PluginVersion::Base do
|
||||
subject(:plugin_version) { described_class.new(plugin) }
|
||||
let(:plugin) { WPScan::Plugin.new(slug, target) }
|
||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||
let(:default_finders) { %w[Readme] }
|
||||
|
||||
describe '#finders' do
|
||||
after do
|
||||
expect(target).to receive(:content_dir).and_return('wp-content')
|
||||
expect(plugin_version.finders.map { |f| f.class.to_s.demodulize }).to match_array @expected
|
||||
end
|
||||
|
||||
context 'when no related specific finders' do
|
||||
let(:slug) { 'spec' }
|
||||
|
||||
it 'contains the default finders' do
|
||||
@expected = default_finders
|
||||
end
|
||||
end
|
||||
|
||||
# Dynamic Version Finders are not tested here, they are in
|
||||
# spec/lib/finders/dynamic_finder/plugin_versions_spec
|
||||
context 'when specific finders' do
|
||||
let(:specific) do
|
||||
{
|
||||
# None so far
|
||||
}
|
||||
end
|
||||
|
||||
WPScan::DB::DynamicFinders::Plugin.versions_finders_configs.each do |plugin_slug, configs|
|
||||
context "when #{plugin_slug} plugin" do
|
||||
let(:slug) { plugin_slug }
|
||||
|
||||
it 'contains the expected finders (default + specific + the dynamic ones)' do
|
||||
@expected = default_finders + [*specific[plugin_slug]] + configs.keys
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
13
spec/app/finders/plugins/body_pattern_spec.rb
Normal file
13
spec/app/finders/plugins/body_pattern_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Plugins::BodyPattern do
|
||||
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
||||
|
||||
let(:expected_all) { df_expected_all['plugins'] }
|
||||
let(:item_class) { WPScan::Plugin }
|
||||
end
|
||||
end
|
||||
13
spec/app/finders/plugins/comment_spec.rb
Normal file
13
spec/app/finders/plugins/comment_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Plugins::Comment do
|
||||
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
||||
|
||||
let(:expected_all) { df_expected_all['plugins'] }
|
||||
let(:item_class) { WPScan::Plugin }
|
||||
end
|
||||
end
|
||||
15
spec/app/finders/plugins/config_parser_spec.rb
Normal file
15
spec/app/finders/plugins/config_parser_spec.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Plugins::ConfigParser do
|
||||
xit
|
||||
|
||||
# it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
||||
# subject(:finder) { described_class.new(target) }
|
||||
# let(:target) { WPScan::Target.new(url) }
|
||||
# let(:url) { 'http://wp.lab/' }
|
||||
# let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
||||
#
|
||||
# let(:expected_all) { df_expected_all['plugins'] }
|
||||
# let(:item_class) { WPScan::Plugin }
|
||||
# end
|
||||
end
|
||||
45
spec/app/finders/plugins/header_pattern_spec.rb
Normal file
45
spec/app/finders/plugins/header_pattern_spec.rb
Normal file
@@ -0,0 +1,45 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Plugins::HeaderPattern do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
||||
|
||||
def plugin(slug)
|
||||
WPScan::Plugin.new(slug, target)
|
||||
end
|
||||
|
||||
describe '#passive' do
|
||||
after do
|
||||
stub_request(:get, target.url).to_return(headers: headers)
|
||||
|
||||
found = finder.passive
|
||||
|
||||
expect(found).to match_array @expected
|
||||
expect(found.first.found_by).to eql 'Header Pattern (Passive Detection)' unless found.empty?
|
||||
end
|
||||
|
||||
context 'when empty headers' do
|
||||
let(:headers) { {} }
|
||||
|
||||
it 'returns an empty array' do
|
||||
@expected = []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when headers' do
|
||||
before { expect(target).to receive(:content_dir).and_return('wp-content') }
|
||||
|
||||
let(:headers) { JSON.parse(File.read(File.join(fixtures, 'header_pattern_passive_all.html'))) }
|
||||
|
||||
it 'returns the expected plugins' do
|
||||
@expected = []
|
||||
|
||||
WPScan::DB::DynamicFinders::Plugin.passive_header_pattern_finder_configs.each_key do |slug|
|
||||
@expected << plugin(slug)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
13
spec/app/finders/plugins/javascript_var_spec.rb
Normal file
13
spec/app/finders/plugins/javascript_var_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Plugins::JavascriptVar do
|
||||
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
||||
|
||||
let(:expected_all) { df_expected_all['plugins'] }
|
||||
let(:item_class) { WPScan::Plugin }
|
||||
end
|
||||
end
|
||||
12
spec/app/finders/plugins/known_locations_spec.rb
Normal file
12
spec/app/finders/plugins/known_locations_spec.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Plugins::KnownLocations do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'plugins', 'known_locations') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
16
spec/app/finders/plugins/query_parameter_spec.rb
Normal file
16
spec/app/finders/plugins/query_parameter_spec.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Plugins::QueryParameter do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
||||
|
||||
describe '#passive' do
|
||||
its(:passive) { should be nil }
|
||||
end
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
27
spec/app/finders/plugins/urls_in_homepage_spec.rb
Normal file
27
spec/app/finders/plugins/urls_in_homepage_spec.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Plugins::UrlsInHomepage do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'plugins', 'urls_in_homepage') }
|
||||
|
||||
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
|
||||
let(:type) { 'plugins' }
|
||||
let(:uniq_links) { true }
|
||||
let(:uniq_codes) { true }
|
||||
let(:expected_from_links) { (1..4).map { |i| "dl-#{i}" } }
|
||||
let(:expected_from_codes) { (1..6).map { |i| "dc-#{i}" } }
|
||||
end
|
||||
|
||||
describe '#passive' do
|
||||
before do
|
||||
stub_request(:get, finder.target.url)
|
||||
.to_return(body: File.read(File.join(fixtures, 'found.html')))
|
||||
|
||||
expect(finder.target).to receive(:content_dir).at_least(1).and_return('wp-content')
|
||||
end
|
||||
|
||||
xit
|
||||
end
|
||||
end
|
||||
13
spec/app/finders/plugins/xpath_spec.rb
Normal file
13
spec/app/finders/plugins/xpath_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Plugins::Xpath do
|
||||
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
||||
|
||||
let(:expected_all) { df_expected_all['plugins'] }
|
||||
let(:item_class) { WPScan::Plugin }
|
||||
end
|
||||
end
|
||||
14
spec/app/finders/plugins_spec.rb
Normal file
14
spec/app/finders/plugins_spec.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Plugins::Base do
|
||||
subject(:plugins) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
|
||||
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]
|
||||
end
|
||||
end
|
||||
end
|
||||
98
spec/app/finders/theme_version/style_spec.rb
Normal file
98
spec/app/finders/theme_version/style_spec.rb
Normal file
@@ -0,0 +1,98 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::ThemeVersion::Style do
|
||||
subject(:finder) { described_class.new(theme) }
|
||||
let(:theme) { WPScan::Theme.new('spec', target) }
|
||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'theme_version', 'style') }
|
||||
|
||||
before :all do
|
||||
Typhoeus::Config.cache = WPScan::Cache::Typhoeus.new(File.join(SPECS, 'cache'))
|
||||
end
|
||||
|
||||
before do
|
||||
expect(target).to receive(:content_dir).at_least(1).and_return('wp-content')
|
||||
stub_request(:get, /.*.css/).and_return(body: defined?(style_body) ? style_body : '')
|
||||
end
|
||||
|
||||
describe '#passive' do
|
||||
before { expect(finder).to receive(:cached_style?).and_return(cached?) }
|
||||
after { finder.passive }
|
||||
|
||||
context 'when the style_url request has been cached' do
|
||||
let(:cached?) { true }
|
||||
|
||||
it 'calls the style_version' do
|
||||
expect(finder).to receive(:style_version)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the style_url request has not been cached' do
|
||||
let(:cached?) { false }
|
||||
|
||||
it 'returns nil' do
|
||||
expect(finder).to_not receive(:style_version)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#aggressive' do
|
||||
before { expect(finder).to receive(:cached_style?).and_return(cached?) }
|
||||
after { finder.aggressive }
|
||||
|
||||
context 'when the style_url request has been cached' do
|
||||
let(:cached?) { true }
|
||||
|
||||
it 'returns nil' do
|
||||
expect(finder).to_not receive(:style_version)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the style_url request has not been cached' do
|
||||
let(:cached?) { false }
|
||||
|
||||
it 'calls the style_version' do
|
||||
expect(finder).to receive(:style_version)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#cached_style?' do
|
||||
it 'calls the Cache with the correct arguments' do
|
||||
expected = Typhoeus::Request.new(
|
||||
theme.style_url,
|
||||
finder.browser.default_request_params.merge(method: :get)
|
||||
)
|
||||
|
||||
expect(Typhoeus::Config.cache).to receive(:get) { |arg| expect(arg).to eql expected }
|
||||
finder.cached_style?
|
||||
end
|
||||
end
|
||||
|
||||
describe '#style_version' do
|
||||
{
|
||||
'inline' => '1.5.1',
|
||||
'firefart' => '1.0.0',
|
||||
'tralling_quote' => '1.3',
|
||||
'no_version_tag' => nil,
|
||||
'trunk_version' => nil,
|
||||
'no_version' => nil
|
||||
}.each do |file, expected_version|
|
||||
context "when #{file}" do
|
||||
let(:style_body) { File.new(File.join(fixtures, "#{file}.css")) }
|
||||
|
||||
it 'returns the expected version' do
|
||||
expected = if expected_version
|
||||
WPScan::Version.new(
|
||||
expected_version,
|
||||
confidence: 80,
|
||||
interesting_entries: ["#{theme.style_url}, Version: #{expected_version}"]
|
||||
)
|
||||
end
|
||||
|
||||
expect(finder.style_version).to eql expected
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,41 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::ThemeVersion::WooFrameworkMetaGenerator do
|
||||
subject(:finder) { described_class.new(theme) }
|
||||
let(:theme) { WPScan::Theme.new(slug, target) }
|
||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'theme_version', 'woo_framework_meta_generator') }
|
||||
|
||||
before do
|
||||
expect(target).to receive(:content_dir).and_return('wp-content')
|
||||
stub_request(:get, /\.css\z/)
|
||||
end
|
||||
|
||||
describe '#passive' do
|
||||
after do
|
||||
stub_request(:get, target.url).to_return(body: File.read(File.join(fixtures, 'editorial-1.3.5.html')))
|
||||
|
||||
expect(finder.passive).to eql @expected
|
||||
end
|
||||
|
||||
context 'when the theme slug does not match' do
|
||||
let(:slug) { 'spec' }
|
||||
|
||||
it 'returns nil' do
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the theme slug matches' do
|
||||
let(:slug) { 'Editorial' }
|
||||
|
||||
it 'return the expected version' do
|
||||
@expected = WPScan::Version.new(
|
||||
'1.3.5',
|
||||
found_by: 'Woo Framework Meta Generator (Passive Detection)',
|
||||
confidence: 80
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
35
spec/app/finders/theme_version_spec.rb
Normal file
35
spec/app/finders/theme_version_spec.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::ThemeVersion::Base do
|
||||
subject(:theme_version) { described_class.new(theme) }
|
||||
let(:theme) { WPScan::Plugin.new(slug, target) }
|
||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||
let(:slug) { 'spec' }
|
||||
let(:default_finders) { %w[Style WooFrameworkMetaGenerator] }
|
||||
|
||||
describe '#finders' do
|
||||
after do
|
||||
expect(target).to receive(:content_dir).and_return('wp-content')
|
||||
expect(theme_version.finders.map { |f| f.class.to_s.demodulize }).to eql @expected
|
||||
end
|
||||
|
||||
context 'when no related specific finders' do
|
||||
it 'contains the default finders' do
|
||||
@expected = default_finders
|
||||
end
|
||||
end
|
||||
|
||||
context 'when specific finders' do
|
||||
{
|
||||
}.each do |theme_slug, specific_finders|
|
||||
context "when #{theme_slug} theme" do
|
||||
let(:slug) { theme_slug }
|
||||
|
||||
it 'contains the expected finders' do
|
||||
@expected = default_finders + specific_finders
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
12
spec/app/finders/themes/known_locations_spec.rb
Normal file
12
spec/app/finders/themes/known_locations_spec.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Themes::KnownLocations do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'themes', 'known_locations') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
20
spec/app/finders/themes/urls_in_homepage_spec.rb
Normal file
20
spec/app/finders/themes/urls_in_homepage_spec.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Themes::UrlsInHomepage do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'themes', 'urls_in_homepage') }
|
||||
|
||||
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
|
||||
let(:type) { 'themes' }
|
||||
let(:uniq_links) { true }
|
||||
let(:uniq_codes) { true }
|
||||
let(:expected_from_links) { %w[dl-1] }
|
||||
let(:expected_from_codes) { %w[dc-1] }
|
||||
end
|
||||
|
||||
describe '#passive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
14
spec/app/finders/themes_spec.rb
Normal file
14
spec/app/finders/themes_spec.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Themes::Base do
|
||||
subject(:themes) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
|
||||
describe '#finders' do
|
||||
it 'contains the expected finders' do
|
||||
expect(themes.finders.map { |f| f.class.to_s.demodulize })
|
||||
.to eq %w[UrlsInHomepage KnownLocations]
|
||||
end
|
||||
end
|
||||
end
|
||||
36
spec/app/finders/timthumb_version/bad_request_spec.rb
Normal file
36
spec/app/finders/timthumb_version/bad_request_spec.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::TimthumbVersion::BadRequest do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Timthumb.new(url) }
|
||||
let(:url) { 'http://ex.lo/timthumb.php' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'timthumb_version', 'bad_request') }
|
||||
|
||||
describe '#aggressive' do
|
||||
before { stub_request(:get, url).to_return(body: File.read(File.join(fixtures, file))) }
|
||||
after { expect(finder.aggressive).to eql @expected }
|
||||
|
||||
context 'when no version' do
|
||||
let(:file) { 'no_version.php' }
|
||||
|
||||
it 'returns nil' do
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a version' do
|
||||
let(:file) { '2.8.14.php' }
|
||||
|
||||
it 'returns the expected version' do
|
||||
@expected = WPScan::Version.new(
|
||||
'2.8.14',
|
||||
confidence: 90,
|
||||
found_by: 'Bad Request (Aggressive Detection)',
|
||||
interesting_entries: [
|
||||
"#{url}, TimThumb version : 2.8.14"
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
13
spec/app/finders/timthumb_version_spec.rb
Normal file
13
spec/app/finders/timthumb_version_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::TimthumbVersion::Base do
|
||||
subject(:timthumb_version) { described_class.new(target) }
|
||||
let(:target) { WPScan::Timthumb.new(url) }
|
||||
let(:url) { 'http://ex.lo/timthumb.php' }
|
||||
|
||||
describe '#finders' do
|
||||
it 'contains the expected finders' do
|
||||
expect(timthumb_version.finders.map { |f| f.class.to_s.demodulize }).to eq %w[BadRequest]
|
||||
end
|
||||
end
|
||||
end
|
||||
12
spec/app/finders/timthumbs/known_locations_spec.rb
Normal file
12
spec/app/finders/timthumbs/known_locations_spec.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Timthumbs::KnownLocations do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'timthumbs', 'known_locations') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
13
spec/app/finders/timthumbs_spec.rb
Normal file
13
spec/app/finders/timthumbs_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Timthumbs::Base do
|
||||
subject(:timthumb) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
|
||||
describe '#finders' do
|
||||
it 'contains the expected finders' do
|
||||
expect(timthumb.finders.map { |f| f.class.to_s.demodulize }).to eq %w[KnownLocations]
|
||||
end
|
||||
end
|
||||
end
|
||||
62
spec/app/finders/users/author_id_brute_forcing_spec.rb
Normal file
62
spec/app/finders/users/author_id_brute_forcing_spec.rb
Normal file
@@ -0,0 +1,62 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Users::AuthorIdBruteForcing do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'author_id_brute_forcing') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#target_urls' do
|
||||
it 'returns the correct URLs' do
|
||||
expect(finder.target_urls(range: (1..2))).to eql(
|
||||
url + '?author=1' => 1,
|
||||
url + '?author=2' => 2
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#potential_username' do
|
||||
[
|
||||
'4.1.1', '4.1.1-permalink',
|
||||
'3.0', '3.0-permalink',
|
||||
'2.9.2', '2.9.2-permalink'
|
||||
].each do |file|
|
||||
it "returns 'admin' from #{file}.html" do
|
||||
body = File.read(File.join(fixtures, "#{file}.html"))
|
||||
res = Typhoeus::Response.new(body: body)
|
||||
|
||||
expect(finder.username_from_response(res)).to eql 'admin'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#display_name_from_body' do
|
||||
context 'when display name' do
|
||||
[
|
||||
'4.1.1', '4.1.1-permalink',
|
||||
'3.0', '3.0-permalink',
|
||||
'2.9.2', '2.9.2-permalink'
|
||||
].each do |file|
|
||||
it "returns 'admin display_name' from #{file}.html" do
|
||||
body = File.read(File.join(fixtures, "#{file}.html"))
|
||||
|
||||
expect(finder.display_name_from_body(body)).to eql 'admin display_name'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no display_name' do
|
||||
['4.1.1', '3.0', '2.9.2'].each do |file|
|
||||
it "returns nil for #{file}-empty.html" do
|
||||
body = File.read(File.join(fixtures, "#{file}-empty.html"))
|
||||
|
||||
expect(finder.display_name_from_body(body)).to eql nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
27
spec/app/finders/users/author_posts_spec.rb
Normal file
27
spec/app/finders/users/author_posts_spec.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Users::AuthorPosts do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'author_posts') }
|
||||
|
||||
describe '#passive' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#potential_usernames' do
|
||||
it 'returns the expected usernames' do
|
||||
res = Typhoeus::Response.new(body: File.read(File.join(fixtures, 'potential_usernames.html')))
|
||||
|
||||
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]
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
32
spec/app/finders/users/login_error_messages_spec.rb
Normal file
32
spec/app/finders/users/login_error_messages_spec.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Users::LoginErrorMessages do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'login_error_messages') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#usernames' do
|
||||
let(:opts) { { found: [] } }
|
||||
|
||||
after { expect(subject.usernames(opts)).to eql @expected }
|
||||
|
||||
context 'when no :list provided' do
|
||||
it 'returns an empty list' do
|
||||
@expected = []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :list provided' do
|
||||
let(:opts) { super().merge(list: %w[u1 u2]) }
|
||||
|
||||
it 'returns the expected array' do
|
||||
@expected = opts[:list]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
12
spec/app/finders/users/oembed_api_spec.rb
Normal file
12
spec/app/finders/users/oembed_api_spec.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Users::OembedApi do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'oembed_api') }
|
||||
|
||||
describe '#aggressive' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
102
spec/app/finders/users/rss_generator_spec.rb
Normal file
102
spec/app/finders/users/rss_generator_spec.rb
Normal file
@@ -0,0 +1,102 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Users::RSSGenerator do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { Pathname.new(FINDERS_FIXTURES).join('users', 'rss_generator') }
|
||||
let(:rss_fixture) { File.read(fixtures.join('feed.xml')) }
|
||||
|
||||
describe '#passive, #aggressive' do
|
||||
before do
|
||||
allow(target).to receive(:sub_dir).and_return(false)
|
||||
|
||||
stub_request(:get, target.url).to_return(body: File.read(homepage_fixture))
|
||||
end
|
||||
|
||||
context 'when no RSS link in homepage' do
|
||||
let(:homepage_fixture) { fixtures.join('homepage_no_links.html') }
|
||||
|
||||
its(:passive) { should eql [] }
|
||||
|
||||
it 'returns the expected from #aggressive' do
|
||||
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
|
||||
stub_request(:get, target.url('comments/feed/'))
|
||||
stub_request(:get, target.url('feed/rss/'))
|
||||
stub_request(:get, target.url('feed/rss2/'))
|
||||
|
||||
expect(finder.aggressive).to eql [
|
||||
CMSScanner::User.new(
|
||||
'admin',
|
||||
confidence: 50,
|
||||
found_by: 'Rss Generator (Aggressive Detection)'
|
||||
),
|
||||
CMSScanner::User.new(
|
||||
'Aa Días-Gildés',
|
||||
confidence: 50,
|
||||
found_by: 'Rss Generator (Aggressive Detection)'
|
||||
)
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
context 'when RSS link in homepage' do
|
||||
let(:homepage_fixture) { File.join(fixtures, 'homepage_links.html') }
|
||||
|
||||
it 'returns the expected from #passive' do
|
||||
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
|
||||
|
||||
expect(finder.passive).to eql [
|
||||
CMSScanner::User.new(
|
||||
'admin',
|
||||
confidence: 50,
|
||||
found_by: 'Rss Generator (Passive Detection)'
|
||||
),
|
||||
CMSScanner::User.new(
|
||||
'Aa Días-Gildés',
|
||||
confidence: 50,
|
||||
found_by: 'Rss Generator (Passive Detection)'
|
||||
)
|
||||
]
|
||||
end
|
||||
|
||||
context 'when :mixed mode' do
|
||||
it 'avoids checking existing URL/s from #passive' do
|
||||
stub_request(:get, target.url('comments/feed/')).to_return(body: rss_fixture)
|
||||
|
||||
expect(finder.aggressive(mode: :mixed)).to eql [
|
||||
CMSScanner::User.new(
|
||||
'admin',
|
||||
confidence: 50,
|
||||
found_by: 'Rss Generator (Aggressive Detection)'
|
||||
),
|
||||
CMSScanner::User.new(
|
||||
'Aa Días-Gildés',
|
||||
confidence: 50,
|
||||
found_by: 'Rss Generator (Aggressive Detection)'
|
||||
)
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no mode' do
|
||||
it 'checks the first URL detected from the URLs' do
|
||||
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
|
||||
|
||||
expect(finder.aggressive).to eql [
|
||||
CMSScanner::User.new(
|
||||
'admin',
|
||||
confidence: 50,
|
||||
found_by: 'Rss Generator (Aggressive Detection)'
|
||||
),
|
||||
CMSScanner::User.new(
|
||||
'Aa Días-Gildés',
|
||||
confidence: 50,
|
||||
found_by: 'Rss Generator (Aggressive Detection)'
|
||||
)
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
47
spec/app/finders/users/wp_json_api_spec.rb
Normal file
47
spec/app/finders/users/wp_json_api_spec.rb
Normal file
@@ -0,0 +1,47 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Users::WpJsonApi do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'wp_json_api') }
|
||||
|
||||
describe '#aggressive' do
|
||||
before do
|
||||
# allow(target).to receive(:content_dir).and_return('wp-content')
|
||||
allow(target).to receive(:sub_dir).and_return(false)
|
||||
stub_request(:get, finder.api_url).to_return(body: body)
|
||||
end
|
||||
|
||||
context 'when not a JSON response' do
|
||||
let(:body) { '' }
|
||||
|
||||
its(:aggressive) { should eql([]) }
|
||||
end
|
||||
|
||||
context 'when a JSON response' do
|
||||
context 'when unauthorised' do
|
||||
let(:body) { File.read(File.join(fixtures, '401.json')) }
|
||||
|
||||
its(:aggressive) { should eql([]) }
|
||||
end
|
||||
|
||||
context 'when limited exposure (WP >= 4.7.1)' do
|
||||
let(:body) { File.read(File.join(fixtures, '4.7.2.json')) }
|
||||
|
||||
it 'returns the expected array of users' do
|
||||
users = finder.aggressive
|
||||
|
||||
expect(users.size).to eql 1
|
||||
|
||||
user = users.first
|
||||
|
||||
expect(user.id).to eql 1
|
||||
expect(user.username).to eql 'admin'
|
||||
expect(user.confidence).to eql 100
|
||||
expect(user.interesting_entries).to eql ['http://wp.lab/wp-json/wp/v2/users/']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
14
spec/app/finders/users_spec.rb
Normal file
14
spec/app/finders/users_spec.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::Users::Base do
|
||||
subject(:user) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
|
||||
describe '#finders' do
|
||||
it 'contains the expected finders' do
|
||||
expect(user.finders.map { |f| f.class.to_s.demodulize })
|
||||
.to eq %w[AuthorPosts WpJsonApi OembedApi RSSGenerator AuthorIdBruteForcing LoginErrorMessages]
|
||||
end
|
||||
end
|
||||
end
|
||||
97
spec/app/finders/wp_version/atom_generator_spec.rb
Normal file
97
spec/app/finders/wp_version/atom_generator_spec.rb
Normal file
@@ -0,0 +1,97 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::WpVersion::AtomGenerator do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { Pathname.new(FINDERS_FIXTURES).join('wp_version', 'atom_generator') }
|
||||
let(:atom_fixture) { File.read(fixtures.join('feed', 'atom')) }
|
||||
|
||||
describe '#passive, #aggressive' do
|
||||
before do
|
||||
allow(target).to receive(:sub_dir).and_return(false)
|
||||
|
||||
stub_request(:get, target.url).to_return(body: File.read(homepage_fixture))
|
||||
end
|
||||
|
||||
context 'when no atom links in homepage' do
|
||||
let(:homepage_fixture) { fixtures.join('no_links.html') }
|
||||
|
||||
its(:passive) { should eql [] }
|
||||
|
||||
it 'returns the expected from #aggressive' do
|
||||
stub_request(:get, target.url('feed/atom/')).to_return(body: atom_fixture)
|
||||
stub_request(:get, target.url('?feed=atom'))
|
||||
|
||||
expect(finder.aggressive).to eql [
|
||||
WPScan::WpVersion.new(
|
||||
'4.0',
|
||||
confidence: 80,
|
||||
found_by: 'Atom Generator (Aggressive Detection)',
|
||||
interesting_entries: [
|
||||
"#{target.url('feed/atom/')}, Match: '<generator uri=\"https://wordpress.org/\" version=\"4.0\">" \
|
||||
"WordPress</generator>'"
|
||||
]
|
||||
)
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
context 'when atom links in homepage' do
|
||||
let(:homepage_fixture) { File.join(fixtures, 'links.html') }
|
||||
|
||||
it 'returns the expected from #passive' do
|
||||
stub_request(:get, target.url('?feed=atom')).to_return(body: atom_fixture)
|
||||
|
||||
expect(finder.passive).to eql [
|
||||
WPScan::WpVersion.new(
|
||||
'4.0',
|
||||
confidence: 80,
|
||||
found_by: 'Atom Generator (Passive Detection)',
|
||||
interesting_entries: [
|
||||
"#{target.url('?feed=atom')}, Match: '<generator uri=\"https://wordpress.org/\" version=\"4.0\">" \
|
||||
"WordPress</generator>'"
|
||||
]
|
||||
)
|
||||
]
|
||||
end
|
||||
|
||||
context 'when :mixed mode' do
|
||||
it 'avoids checking existing URL/s from #passive' do
|
||||
stub_request(:get, target.url('feed/atom/')).to_return(body: atom_fixture)
|
||||
|
||||
expect(finder.aggressive(mode: :mixed)).to eql [
|
||||
WPScan::WpVersion.new(
|
||||
'4.0',
|
||||
confidence: 80,
|
||||
found_by: 'Atom Generator (Aggressive Detection)',
|
||||
interesting_entries: [
|
||||
"#{target.url('feed/atom/')}, Match: '<generator uri=\"https://wordpress.org/\" version=\"4.0\">" \
|
||||
"WordPress</generator>'"
|
||||
]
|
||||
)
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no mode' do
|
||||
it 'checks all the URLs' do
|
||||
stub_request(:get, target.url('feed/atom/')).to_return(body: atom_fixture)
|
||||
stub_request(:get, target.url('?feed=atom'))
|
||||
|
||||
expect(finder.aggressive).to eql [
|
||||
WPScan::WpVersion.new(
|
||||
'4.0',
|
||||
confidence: 80,
|
||||
found_by: 'Atom Generator (Aggressive Detection)',
|
||||
interesting_entries: [
|
||||
"#{target.url('feed/atom/')}, Match: '<generator uri=\"https://wordpress.org/\" version=\"4.0\">" \
|
||||
"WordPress</generator>'"
|
||||
]
|
||||
)
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
10
spec/app/finders/wp_version/rdf_generator_spec.rb
Normal file
10
spec/app/finders/wp_version/rdf_generator_spec.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::WpVersion::RDFGenerator do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'rdf_generator') }
|
||||
|
||||
xit
|
||||
end
|
||||
49
spec/app/finders/wp_version/readme_spec.rb
Normal file
49
spec/app/finders/wp_version/readme_spec.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::WpVersion::Readme do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'readme') }
|
||||
let(:readme_url) { url + 'readme.html' }
|
||||
|
||||
describe '#aggressive' do
|
||||
before { stub_request(:get, readme_url).to_return(body: File.read(File.join(fixtures, file))) }
|
||||
|
||||
after do
|
||||
expect(target).to receive(:sub_dir).and_return(false)
|
||||
expect(finder.aggressive).to eql @expected
|
||||
end
|
||||
|
||||
context 'when no version' do
|
||||
let(:file) { 'no_version.html' }
|
||||
|
||||
it 'returns nil' do
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid version number' do
|
||||
let(:file) { 'invalid.html' }
|
||||
|
||||
it 'returns nil' do
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when present and valid' do
|
||||
let(:file) { '4.0.html' }
|
||||
|
||||
it 'returns the expected version' do
|
||||
@expected = WPScan::WpVersion.new(
|
||||
'4.0',
|
||||
confidence: 90,
|
||||
found_by: 'Readme (Aggressive Detection)',
|
||||
interesting_entries: [
|
||||
"#{readme_url}, Match: 'Version 4.0'"
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
10
spec/app/finders/wp_version/rss_generator_spec.rb
Normal file
10
spec/app/finders/wp_version/rss_generator_spec.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::WpVersion::RSSGenerator do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'rss_generator') }
|
||||
|
||||
xit
|
||||
end
|
||||
10
spec/app/finders/wp_version/unique_fingerprinting_spec.rb
Normal file
10
spec/app/finders/wp_version/unique_fingerprinting_spec.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Finders::WpVersion::UniqueFingerprinting do
|
||||
subject(:finder) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'unique_fingerprinting') }
|
||||
|
||||
xit
|
||||
end
|
||||
25
spec/app/finders/wp_version_spec.rb
Normal file
25
spec/app/finders/wp_version_spec.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
require 'spec_helper'
|
||||
|
||||
# If this file is tested alone (rspec path-to-this-file), then there will be an error about
|
||||
# constants not being intilialized. This is due to the Dynamic Finders.
|
||||
|
||||
describe WPScan::Finders::WpVersion::Base do
|
||||
subject(:wp_version) { described_class.new(target) }
|
||||
let(:target) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://ex.lo/' }
|
||||
|
||||
describe '#finders' do
|
||||
let(:expected) { %w[RSSGenerator AtomGenerator RDFGenerator Readme UniqueFingerprinting] }
|
||||
|
||||
let(:expected_dynamic_finders) { WPScan::DB::DynamicFinders::Wordpress.versions_finders_configs.keys }
|
||||
|
||||
it 'contains the expected finders' do
|
||||
finders = wp_version.finders.map { |f| f.class.to_s.demodulize }
|
||||
|
||||
expect(finders).to match_array expected + expected_dynamic_finders
|
||||
|
||||
expect(finders.first).to eql 'RSSGenerator'
|
||||
expect(finders.last).to eql 'UniqueFingerprinting'
|
||||
end
|
||||
end
|
||||
end
|
||||
9
spec/app/models/interesting_finding_spec.rb
Normal file
9
spec/app/models/interesting_finding_spec.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::InterestingFinding do
|
||||
it_behaves_like WPScan::References do
|
||||
subject(:finding) { described_class.new('http://e.org/file.php', opts) }
|
||||
let(:opts) { { references: references } }
|
||||
let(:references) { {} }
|
||||
end
|
||||
end
|
||||
10
spec/app/models/media_spec.rb
Normal file
10
spec/app/models/media_spec.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Media do
|
||||
subject(:media) { described_class.new(url) }
|
||||
let(:url) { 'http://e.oeg/?attachment_id=2' }
|
||||
|
||||
describe '#new' do
|
||||
its(:url) { should eql url }
|
||||
end
|
||||
end
|
||||
192
spec/app/models/plugin_spec.rb
Normal file
192
spec/app/models/plugin_spec.rb
Normal file
@@ -0,0 +1,192 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Plugin do
|
||||
subject(:plugin) { described_class.new(slug, blog, opts) }
|
||||
let(:slug) { 'spec' }
|
||||
let(:blog) { WPScan::Target.new('http://wp.lab/') }
|
||||
let(:opts) { {} }
|
||||
|
||||
before { expect(blog).to receive(:content_dir).and_return('wp-content') }
|
||||
|
||||
describe '#new' do
|
||||
its(:url) { should eql 'http://wp.lab/wp-content/plugins/spec/' }
|
||||
end
|
||||
|
||||
describe '#version' do
|
||||
after do
|
||||
expect(WPScan::Finders::PluginVersion::Base).to receive(:find).with(plugin, @expected_opts)
|
||||
|
||||
plugin.version(version_opts)
|
||||
end
|
||||
|
||||
let(:default_opts) { {} }
|
||||
|
||||
context 'when no :detection_mode' do
|
||||
context 'when no :mode opt supplied' do
|
||||
let(:version_opts) { { something: 'k' } }
|
||||
|
||||
it 'calls the finder with the correct parameters' do
|
||||
@expected_opts = version_opts
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :mode supplied' do
|
||||
let(:version_opts) { { mode: :passive } }
|
||||
|
||||
it 'calls the finder with the correct parameters' do
|
||||
@expected_opts = default_opts.merge(mode: :passive)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :detection_mode' do
|
||||
let(:opts) { super().merge(mode: :passive) }
|
||||
|
||||
context 'when no :mode' do
|
||||
let(:version_opts) { {} }
|
||||
|
||||
it 'calls the finder without mode' do
|
||||
@expected_opts = version_opts
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :mode' do
|
||||
let(:version_opts) { { mode: :mixed } }
|
||||
|
||||
it 'calls the finder with the :mixed mode' do
|
||||
@expected_opts = default_opts.merge(mode: :mixed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#latest_version, #last_updated, #popular' do
|
||||
context 'when none' do
|
||||
let(:slug) { 'vulnerable-not-popular' }
|
||||
|
||||
its(:latest_version) { should be_nil }
|
||||
its(:last_updated) { should be_nil }
|
||||
its(:popular?) { should be false }
|
||||
end
|
||||
|
||||
context 'when values' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
|
||||
its(:latest_version) { should eql WPScan::Version.new('2.0') }
|
||||
its(:last_updated) { should eql '2015-05-16T00:00:00.000Z' }
|
||||
its(:popular?) { should be true }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#outdated?' do
|
||||
context 'when last_version' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
|
||||
context 'when no version' do
|
||||
before { expect(plugin).to receive(:version).at_least(1).and_return(nil) }
|
||||
|
||||
its(:outdated?) { should eql false }
|
||||
end
|
||||
|
||||
context 'when version' do
|
||||
before { expect(plugin).to receive(:version).at_least(1).and_return(WPScan::Version.new(version_number)) }
|
||||
|
||||
context 'when version < last_version' do
|
||||
let(:version_number) { '1.2' }
|
||||
|
||||
its(:outdated?) { should eql true }
|
||||
end
|
||||
|
||||
context 'when version >= last_version' do
|
||||
let(:version_number) { '3.0' }
|
||||
|
||||
its(:outdated?) { should eql false }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no last_version' do
|
||||
let(:slug) { 'vulnerable-not-popular' }
|
||||
|
||||
context 'when no version' do
|
||||
before { expect(plugin).to receive(:version).at_least(1).and_return(nil) }
|
||||
|
||||
its(:outdated?) { should eql false }
|
||||
end
|
||||
|
||||
context 'when version' do
|
||||
before { expect(plugin).to receive(:version).at_least(1).and_return(WPScan::Version.new('1.0')) }
|
||||
|
||||
its(:outdated?) { should eql false }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#vulnerabilities' do
|
||||
after do
|
||||
expect(plugin.vulnerabilities).to eq @expected
|
||||
expect(plugin.vulnerable?).to eql @expected.empty? ? false : true
|
||||
end
|
||||
|
||||
context 'when plugin not in the DB' do
|
||||
let(:slug) { 'not-in-db' }
|
||||
|
||||
it 'returns an empty array' do
|
||||
@expected = []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when in the DB' do
|
||||
context 'when no vulnerabilities' do
|
||||
let(:slug) { 'no-vulns-popular' }
|
||||
|
||||
it 'returns an empty array' do
|
||||
@expected = []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when vulnerabilities' do
|
||||
let(:slug) { 'vulnerable-not-popular' }
|
||||
let(:all_vulns) do
|
||||
[
|
||||
WPScan::Vulnerability.new(
|
||||
'First Vuln',
|
||||
{ wpvulndb: '1' },
|
||||
'LFI',
|
||||
'6.3.10'
|
||||
),
|
||||
WPScan::Vulnerability.new('No Fixed In', wpvulndb: '2')
|
||||
]
|
||||
end
|
||||
|
||||
context 'when no plugin version' do
|
||||
before { expect(plugin).to receive(:version).at_least(1).and_return(false) }
|
||||
|
||||
it 'returns all the vulnerabilities' do
|
||||
@expected = all_vulns
|
||||
end
|
||||
end
|
||||
|
||||
context 'when plugin version' do
|
||||
before { expect(plugin).to receive(:version).at_least(1).and_return(WPScan::Version.new(number)) }
|
||||
|
||||
context 'when < to a fixed_in' do
|
||||
let(:number) { '5.0' }
|
||||
|
||||
it 'returns it' do
|
||||
@expected = all_vulns
|
||||
end
|
||||
end
|
||||
|
||||
context 'when >= to a fixed_in' do
|
||||
let(:number) { '6.3.10' }
|
||||
|
||||
it 'does not return it ' do
|
||||
@expected = [all_vulns.last]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
165
spec/app/models/theme_spec.rb
Normal file
165
spec/app/models/theme_spec.rb
Normal file
@@ -0,0 +1,165 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Theme do
|
||||
subject(:theme) { described_class.new(slug, blog, opts) }
|
||||
let(:slug) { 'spec' }
|
||||
let(:blog) { WPScan::Target.new('http://wp.lab/') }
|
||||
let(:opts) { {} }
|
||||
let(:fixtures) { File.join(FIXTURES, 'models', 'theme') }
|
||||
|
||||
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(File.join(fixtures, 'style.css')))
|
||||
end
|
||||
|
||||
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' }
|
||||
|
||||
its(:style_name) { should eql 'Twenty Fifteen' }
|
||||
its(:style_uri) { should eql 'https://wordpress.org/themes/twentyfifteen' }
|
||||
its(:author) { should eql 'the WordPress team' }
|
||||
its(:author_uri) { should eql nil }
|
||||
its(:template) { should eql nil }
|
||||
its(:description) { should eql 'Our 2015 default theme is clean, blog-focused.' }
|
||||
its(:license) { should eql 'GNU General Public License v2 or later' }
|
||||
its(:license_uri) { should eql 'http://www.gnu.org/licenses/gpl-2.0.html' }
|
||||
its(:tags) { should eql 'black, blue, gray, pink, purple, white, yellow.' }
|
||||
its(:text_domain) { should eql 'twentyfifteen' }
|
||||
|
||||
context 'when opts[:style_url]' do
|
||||
let(:opts) { super().merge(style_url: 'http://wp.lab/wp-content/themes/spec/custom.css') }
|
||||
|
||||
its(:style_url) { should eql opts[:style_url] }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#version' do
|
||||
after do
|
||||
stub_request(:get, /.*\.css\z/)
|
||||
.to_return(body: File.read(File.join(fixtures, 'style.css')))
|
||||
|
||||
expect(WPScan::Finders::ThemeVersion::Base).to receive(:find).with(theme, @expected_opts)
|
||||
theme.version(version_opts)
|
||||
end
|
||||
|
||||
let(:default_opts) { {} }
|
||||
|
||||
context 'when no :detection_mode' do
|
||||
context 'when no :mode opt supplied' do
|
||||
let(:version_opts) { { something: 'k' } }
|
||||
|
||||
it 'calls the finder with the correct parameters' do
|
||||
@expected_opts = version_opts
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :mode supplied' do
|
||||
let(:version_opts) { { mode: :passive } }
|
||||
|
||||
it 'calls the finder with the correct parameters' do
|
||||
@expected_opts = default_opts.merge(mode: :passive)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :detection_mode' do
|
||||
let(:opts) { super().merge(mode: :passive) }
|
||||
|
||||
context 'when no :mode' do
|
||||
let(:version_opts) { {} }
|
||||
|
||||
it 'calls the finder without mode' do
|
||||
@expected_opts = version_opts
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :mode' do
|
||||
let(:version_opts) { { mode: :mixed } }
|
||||
|
||||
it 'calls the finder with the :mixed mode' do
|
||||
@expected_opts = default_opts.merge(mode: :mixed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#vulnerabilities' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#parent_theme' do
|
||||
before do
|
||||
stub_request(:get, blog.url('wp-content/themes/spec/style.css'))
|
||||
.to_return(body: File.read(File.join(fixtures, main_theme)))
|
||||
end
|
||||
|
||||
context 'when no template' do
|
||||
let(:main_theme) { 'style.css' }
|
||||
|
||||
it 'returns nil' do
|
||||
expect(theme.parent_theme).to eql nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a template' do
|
||||
let(:main_theme) { 'child_style.css' }
|
||||
let(:parent_url) { blog.url('wp-content/themes/twentyfourteen/custom.css') }
|
||||
|
||||
before do
|
||||
stub_request(:get, parent_url)
|
||||
.to_return(body: File.read(File.join(fixtures, 'style.css')))
|
||||
end
|
||||
|
||||
%w[child_style windows_line_endings].each do |fixture|
|
||||
context "when #{fixture}" do
|
||||
let(:main_theme) { "#{fixture}.css" }
|
||||
|
||||
it 'returns the expected theme' do
|
||||
parent = theme.parent_theme
|
||||
|
||||
expect(parent).to eql described_class.new(
|
||||
'twentyfourteen', blog,
|
||||
style_url: parent_url,
|
||||
confidence: 100,
|
||||
found_by: 'Parent Themes (Passive Detection)'
|
||||
)
|
||||
expect(parent.style_url).to eql parent_url
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#parent_themes' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#==' do
|
||||
before { stub_request(:get, /.*\.css\z/) }
|
||||
|
||||
context 'when default style' do
|
||||
it 'returns true when equal' do
|
||||
expect(theme == described_class.new(slug, blog, opts)).to be true
|
||||
end
|
||||
|
||||
it 'returns false when not equal' do
|
||||
expect(theme == described_class.new(slug, blog, opts.merge(style_url: 'spec.css'))).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when custom style' do
|
||||
let(:opts) { super().merge(style_url: 'spec.css') }
|
||||
|
||||
it 'returns true when equal' do
|
||||
expect(theme == described_class.new(slug, blog, opts.merge(style_url: 'spec.css'))).to be true
|
||||
end
|
||||
|
||||
it 'returns false when not equal' do
|
||||
expect(theme == described_class.new(slug, blog, opts.merge(style_url: 'spec2.css'))).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
126
spec/app/models/timthumb_spec.rb
Normal file
126
spec/app/models/timthumb_spec.rb
Normal file
@@ -0,0 +1,126 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::Timthumb do
|
||||
subject(:timthumb) { described_class.new(url, opts) }
|
||||
let(:url) { 'http://wp.lab/wp-content/timthumb.php' }
|
||||
let(:fixtures) { File.join(FIXTURES, 'models', 'timthumb') }
|
||||
let(:opts) { {} }
|
||||
|
||||
describe '#new' do
|
||||
its(:url) { should eql url }
|
||||
end
|
||||
|
||||
# The fact that the finders should only be called once is handled by the
|
||||
# vulnerabilities, vulnerable? specs below
|
||||
describe '#version' do
|
||||
after do
|
||||
expect(WPScan::Finders::TimthumbVersion::Base).to receive(:find).with(timthumb, @expected_opts)
|
||||
|
||||
timthumb.version(version_opts)
|
||||
end
|
||||
|
||||
context 'when no :version_detection' do
|
||||
context 'when no :mode opt supplied' do
|
||||
let(:version_opts) { { something: 'k' } }
|
||||
|
||||
it 'calls the finder with the correct parameters' do
|
||||
@expected_opts = version_opts
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :mode supplied' do
|
||||
let(:version_opts) { { mode: :passive } }
|
||||
|
||||
it 'calls the finder with the correct parameters' do
|
||||
@expected_opts = { mode: :passive }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :version_detection' do
|
||||
let(:opts) { super().merge(mode: :passive) }
|
||||
|
||||
context 'when no :mode' do
|
||||
let(:version_opts) { {} }
|
||||
|
||||
it 'calls the finder with the :passive mode' do
|
||||
@expected_opts = version_opts
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :mode' do
|
||||
let(:version_opts) { { mode: :mixed } }
|
||||
|
||||
it 'calls the finder with the :mixed mode' do
|
||||
@expected_opts = { mode: :mixed }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#webshot_enabled?' do
|
||||
before do
|
||||
stub_request(:get, /#{timthumb.url}\?src=.*&webshot=1/i)
|
||||
.to_return(body: File.read(File.join(fixtures, fixture)))
|
||||
end
|
||||
|
||||
context 'when enabled' do
|
||||
let(:fixture) { '2.8.13_webshot_enabled.html' }
|
||||
|
||||
its(:webshot_enabled?) { should eql true }
|
||||
end
|
||||
|
||||
context 'when disabled' do
|
||||
let(:fixture) { '2.8.13_webshot_disabled.html' }
|
||||
|
||||
its(:webshot_enabled?) { should eql false }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#vulnerabilities, #vulnerable?' do
|
||||
before { expect(WPScan::Finders::TimthumbVersion::Base).to receive(:find).and_return(version) }
|
||||
|
||||
context 'when no version' do
|
||||
let(:version) { false }
|
||||
|
||||
its(:vulnerabilities) { should eq([timthumb.rce_webshot_vuln, timthumb.rce_132_vuln]) }
|
||||
it { should be_vulnerable }
|
||||
end
|
||||
|
||||
context 'when version' do
|
||||
let(:version) { WPScan::Version.new(version_number) }
|
||||
|
||||
context 'when version >= 2.8.14' do
|
||||
let(:version_number) { '2.8.14' }
|
||||
|
||||
its(:vulnerabilities) { should eq([]) }
|
||||
it { should_not be_vulnerable }
|
||||
end
|
||||
|
||||
context 'when version < 1.33' do
|
||||
let(:version_number) { '1.20' }
|
||||
|
||||
its(:vulnerabilities) { should eq([timthumb.rce_132_vuln]) }
|
||||
it { should be_vulnerable }
|
||||
end
|
||||
|
||||
context 'when version > 1.35 and < 2.8.13' do
|
||||
let(:version_number) { '2.8.10' }
|
||||
|
||||
context 'when webshot enabled' do
|
||||
before { expect(timthumb).to receive(:webshot_enabled?).and_return(true) }
|
||||
|
||||
its(:vulnerabilities) { should eq([timthumb.rce_webshot_vuln]) }
|
||||
it { should be_vulnerable }
|
||||
end
|
||||
|
||||
context 'when webshot disabled' do
|
||||
before { expect(timthumb).to receive(:webshot_enabled?).and_return(false) }
|
||||
|
||||
its(:vulnerabilities) { should eq([]) }
|
||||
it { should_not be_vulnerable }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
130
spec/app/models/wp_item_spec.rb
Normal file
130
spec/app/models/wp_item_spec.rb
Normal file
@@ -0,0 +1,130 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::WpItem do
|
||||
subject(:wp_item) { described_class.new(slug, blog, opts) }
|
||||
let(:slug) { 'test_item' }
|
||||
let(:blog) { WPScan::Target.new(url) }
|
||||
let(:url) { 'http://wp.lab/' }
|
||||
let(:opts) { {} }
|
||||
|
||||
its(:blog) { should eql blog }
|
||||
|
||||
describe '#new' do
|
||||
context 'when no opts' do
|
||||
its(:slug) { should eql slug }
|
||||
its(:detection_opts) { should eql(mode: nil) }
|
||||
its(:version_detection_opts) { should eql({}) }
|
||||
end
|
||||
|
||||
context 'when :mode' do
|
||||
let(:opts) { super().merge(mode: :passive, version_detection: { mode: :aggressive }) }
|
||||
|
||||
its(:detection_opts) { should eql(mode: :passive) }
|
||||
its(:version_detection_opts) { should eql(mode: :aggressive) }
|
||||
end
|
||||
|
||||
context 'when the slug contains encoded chars' do
|
||||
let(:slug) { 'theme%212%23a' }
|
||||
|
||||
its(:slug) { should eql 'theme!2#a' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#url' do
|
||||
context 'when no opts[:url]' do
|
||||
its(:url) { should eql nil }
|
||||
end
|
||||
|
||||
context 'when opts[:url]' do
|
||||
let(:opts) { super().merge(url: item_url) }
|
||||
let(:item_url) { "#{url}item/" }
|
||||
|
||||
context 'when path given' do
|
||||
it 'appends it' do
|
||||
expect(wp_item.url('path')).to eql "#{item_url}path"
|
||||
end
|
||||
end
|
||||
|
||||
it 'encodes the path' do
|
||||
expect(wp_item.url('#t#')).to eql "#{item_url}%23t%23"
|
||||
expect(wp_item.url('t .txt')).to eql "#{item_url}t%20.txt"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#==' do
|
||||
context 'when the same slug' do
|
||||
it 'returns true' do
|
||||
other = described_class.new(slug, blog)
|
||||
|
||||
expect(wp_item == other).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when another object' do
|
||||
it 'returns false' do
|
||||
expect(wp_item == 'string').to be false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when different slugs' do
|
||||
it 'returns false' do
|
||||
other = described_class.new('another', blog)
|
||||
|
||||
expect(wp_item == other).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#latest_version' do
|
||||
# Handled in plugin_spec / theme_spec
|
||||
end
|
||||
|
||||
describe '#popular?' do
|
||||
# Handled in plugin_spec / theme_spec
|
||||
end
|
||||
|
||||
describe '#last_updated' do
|
||||
# Handled in plugin_spec / theme_spec
|
||||
end
|
||||
|
||||
describe '#outdated?' do
|
||||
# Handled in plugin_spec / theme_spec
|
||||
end
|
||||
|
||||
describe '#to_s' do
|
||||
its(:to_s) { should eql slug }
|
||||
end
|
||||
|
||||
describe '#classify' do
|
||||
its(:classify) { should eql :TestItem }
|
||||
|
||||
context 'when it starts with a digit' do
|
||||
let(:slug) { '2test' }
|
||||
|
||||
its(:classify) { should eql :D_2test }
|
||||
|
||||
context 'when a digit and -' do
|
||||
let(:slug) { '23-test' }
|
||||
|
||||
its(:classify) { should eql :D_23Test }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#readme_url' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#changelog_url' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#directory_listing?' do
|
||||
xit
|
||||
end
|
||||
|
||||
describe '#error_log?' do
|
||||
xit
|
||||
end
|
||||
end
|
||||
89
spec/app/models/wp_version_spec.rb
Normal file
89
spec/app/models/wp_version_spec.rb
Normal file
@@ -0,0 +1,89 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::WpVersion do
|
||||
describe '#new' do
|
||||
context 'when invalid number' do
|
||||
it 'raises an error' do
|
||||
expect { described_class.new('aa') }.to raise_error WPScan::InvalidWordPressVersion
|
||||
end
|
||||
end
|
||||
|
||||
context 'when valid number' do
|
||||
it 'create the instance' do
|
||||
version = described_class.new(4.0)
|
||||
|
||||
expect(version).to be_a described_class
|
||||
expect(version.number).to eql '4.0'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.all' do
|
||||
it 'returns the correct values' do
|
||||
expect(described_class.all).to eql %w[4.4 4.0 3.9.1 3.8.2 3.8.1 3.8]
|
||||
end
|
||||
end
|
||||
|
||||
describe '.valid?' do
|
||||
after { expect(described_class.valid?(@number)).to eq @expected }
|
||||
|
||||
it 'returns false' do
|
||||
@number = 'aaa'
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@number = '4.0'
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#vulnerabilities' do
|
||||
subject(:version) { described_class.new(number) }
|
||||
|
||||
context 'when no vulns' do
|
||||
let(:number) { '4.4' }
|
||||
|
||||
its(:vulnerabilities) { should eql([]) }
|
||||
end
|
||||
|
||||
context 'when vulnerable' do
|
||||
after do
|
||||
expect(version.vulnerabilities).to eq @expected
|
||||
expect(version).to be_vulnerable
|
||||
end
|
||||
|
||||
context 'when a signle vuln' do
|
||||
let(:number) { '3.8' }
|
||||
|
||||
it 'returns the expected result' do
|
||||
@expected = [WPScan::Vulnerability.new(
|
||||
'WP 3.8 - Vuln 1',
|
||||
{ url: %w[url-4], osvdb: %w[11], wpvulndb: '3' },
|
||||
'AUTHBYPASS'
|
||||
)]
|
||||
end
|
||||
end
|
||||
|
||||
context 'when multiple vulns' do
|
||||
let(:number) { '3.8.1' }
|
||||
|
||||
it 'returns the expected results' do
|
||||
@expected = [
|
||||
WPScan::Vulnerability.new(
|
||||
'WP 3.8.1 - Vuln 1',
|
||||
{ wpvulndb: '1' },
|
||||
'SQLI'
|
||||
),
|
||||
WPScan::Vulnerability.new(
|
||||
'WP 3.8.1 - Vuln 2',
|
||||
{ url: %w[url-2 url-3], osvdb: %w[10], cve: %w[2014-0166], wpvulndb: '2' },
|
||||
nil,
|
||||
'3.8.2'
|
||||
)
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
9
spec/app/models/xml_rpc_spec.rb
Normal file
9
spec/app/models/xml_rpc_spec.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WPScan::XMLRPC do
|
||||
subject(:xml_rpc) { described_class.new('http//e.org/xmlrpc.php') }
|
||||
|
||||
describe '#references' do
|
||||
its(:references) { should_not be_empty }
|
||||
end
|
||||
end
|
||||
37
spec/app/views_spec.rb
Normal file
37
spec/app/views_spec.rb
Normal file
@@ -0,0 +1,37 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'App::Views' do
|
||||
let(:target_url) { 'http://ex.lo/' }
|
||||
let(:target) { WPScan::Target.new(target_url) }
|
||||
let(:fixtures) { File.join(SPECS, 'output') }
|
||||
|
||||
# CliNoColour is used to test the CLI output to avoid the painful colours
|
||||
# in the expected output.
|
||||
%i[JSON CliNoColour].each do |formatter|
|
||||
context "when #{formatter}" do
|
||||
it_behaves_like 'App::Views::WpVersion'
|
||||
it_behaves_like 'App::Views::MainTheme'
|
||||
it_behaves_like 'App::Views::Enumeration'
|
||||
|
||||
let(:parsed_options) { { url: target_url, format: formatter.to_s.underscore.dasherize } }
|
||||
|
||||
before do
|
||||
controller.class.parsed_options = parsed_options
|
||||
# Resets the formatter to ensure the correct one is loaded
|
||||
controller.class.class_variable_set(:@@formatter, nil)
|
||||
end
|
||||
|
||||
after do
|
||||
view_filename = defined?(expected_view) ? expected_view : view
|
||||
view_filename = "#{view_filename}.#{formatter.to_s.underscore.downcase}"
|
||||
controller_dir = controller.class.to_s.demodulize.underscore.downcase
|
||||
expected_output = File.read(File.join(fixtures, controller_dir, view_filename))
|
||||
|
||||
expect($stdout).to receive(:puts).with(expected_output)
|
||||
|
||||
controller.output(view, @tpl_vars)
|
||||
controller.formatter.beautify # Mandatory to be able to test formatter such as JSON
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
4
spec/cache/.gitignore
vendored
Normal file
4
spec/cache/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
3
spec/fixtures/db/config_backups.txt
vendored
Normal file
3
spec/fixtures/db/config_backups.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#wp-config.php#
|
||||
wp-config.bak
|
||||
wp-config.txt
|
||||
6
spec/fixtures/db/db_exports.txt
vendored
Normal file
6
spec/fixtures/db/db_exports.txt
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{domain_name}.sql
|
||||
wordpress.sql
|
||||
backup/{domain_name}.zip
|
||||
backup/mysql.sql
|
||||
backups/{domain_name}.sql.gz
|
||||
backups/db_backup.sql
|
||||
25726
spec/fixtures/db/dynamic_finders.yml
vendored
Normal file
25726
spec/fixtures/db/dynamic_finders.yml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
25
spec/fixtures/db/plugins.json
vendored
Normal file
25
spec/fixtures/db/plugins.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"no-vulns-popular": {
|
||||
"vulnerabilities": [],
|
||||
"popular": true,
|
||||
"latest_version": "2.0",
|
||||
"last_updated": "2015-05-16T00:00:00.000Z"
|
||||
},
|
||||
"vulnerable-not-popular": {
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"popular": false,
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"title" : "First Vuln",
|
||||
"fixed_in" : "6.3.10",
|
||||
"id" : 1,
|
||||
"vuln_type": "LFI"
|
||||
},
|
||||
{
|
||||
"title": "No Fixed In",
|
||||
"id": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
48
spec/fixtures/db/themes.json
vendored
Normal file
48
spec/fixtures/db/themes.json
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"no-vulns-popular": {
|
||||
"popular": true,
|
||||
"latest_version": "2.0",
|
||||
"last_updated": "2015-05-16T00:00:00.000Z",
|
||||
"vulnerabilities": []
|
||||
},
|
||||
"dignitas-themes": {
|
||||
"popular": true,
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"created_at" : "2015-03-05T19:25:59.000Z",
|
||||
"updated_at" : "2015-03-05T19:37:47.000Z",
|
||||
"references": {
|
||||
"url" : [
|
||||
"http://research.evex.pw/?vuln=6",
|
||||
"http://packetstormsecurity.com/files/130652/"
|
||||
]
|
||||
},
|
||||
"title" : "Dignitas 1.1.9 - Privilage Escalation",
|
||||
"id" : 7825,
|
||||
"vuln_type" : "AUTHBYPASS"
|
||||
}
|
||||
]
|
||||
},
|
||||
"yaaburnee-themes": {
|
||||
"popular": false,
|
||||
"latest_version": null,
|
||||
"last_updated": null,
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"created_at" : "2015-03-05T19:25:44.000Z",
|
||||
"updated_at" : "2015-03-05T19:41:14.000Z",
|
||||
"references": {
|
||||
"url" : [
|
||||
"http://research.evex.pw/?vuln=6",
|
||||
"http://packetstormsecurity.com/files/130652/"
|
||||
]
|
||||
},
|
||||
"title" : "Ya'aburnee 1.0.7 - Privilage Escalation",
|
||||
"id" : 7824,
|
||||
"vuln_type" : "AUTHBYPASS"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
3
spec/fixtures/db/user-agents.txt
vendored
Normal file
3
spec/fixtures/db/user-agents.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Coments should be ignored
|
||||
UA-1
|
||||
UA-2
|
||||
42
spec/fixtures/db/wordpresses.json
vendored
Normal file
42
spec/fixtures/db/wordpresses.json
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"3.8.1": {
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"created_at" : "2014-08-01T10:58:19.000Z",
|
||||
"updated_at" : "2014-09-16T13:52:17.000Z",
|
||||
"title" : "WP 3.8.1 - Vuln 1",
|
||||
"id" : 1,
|
||||
"vuln_type" : "SQLI",
|
||||
"published_date" : null,
|
||||
"fixed_in" : null
|
||||
},
|
||||
{
|
||||
"references" : {
|
||||
"cve" : ["2014-0166"],
|
||||
"osvdb" : ["10"],
|
||||
"url" : ["url-2","url-3"]
|
||||
},
|
||||
"fixed_in" : "3.8.2",
|
||||
"created_at" : "2014-08-01T10:58:19.000Z",
|
||||
"updated_at" : "2014-09-16T13:53:11.000Z",
|
||||
"id" : 2,
|
||||
"title" : "WP 3.8.1 - Vuln 2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"3.8": {
|
||||
"vulnerabilities" : [
|
||||
{
|
||||
"references": {
|
||||
"url" : ["url-4"],
|
||||
"osvdb" : ["11"]
|
||||
},
|
||||
"created_at" : "2014-08-01T10:58:19.000Z",
|
||||
"updated_at" : "2014-09-16T15:45:26.000Z",
|
||||
"title" : "WP 3.8 - Vuln 1",
|
||||
"id" : 3,
|
||||
"vuln_type" : "AUTHBYPASS"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
9
spec/fixtures/db/wp_fingerprints.json
vendored
Normal file
9
spec/fixtures/db/wp_fingerprints.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"path-1": {
|
||||
"hash-1": ["4.0", "3.8"],
|
||||
"hash-2": ["4.4"]
|
||||
},
|
||||
"path-2": {
|
||||
"hash-3": ["3.8.1", "3.8.2", "3.9.1"]
|
||||
}
|
||||
}
|
||||
32374
spec/fixtures/dynamic_finders/expected.yml
vendored
Normal file
32374
spec/fixtures/dynamic_finders/expected.yml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,156 @@
|
||||
<div class="row" id="kb-amz-version">
|
||||
<div class="col-sm-12">
|
||||
<h4>2.1.1</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>
|
||||
Security fix, thanks to Ricardo
|
||||
</li>
|
||||
</ul>
|
||||
<h4>2.0.2</h4>
|
||||
<h4>2.1.0</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>
|
||||
Maintenance release
|
||||
</li>
|
||||
</ul>
|
||||
<h4>2.0.2</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>
|
||||
Css fixes
|
||||
</li>
|
||||
</ul>
|
||||
<h4>2.0.1</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>
|
||||
Import optimization
|
||||
</li>
|
||||
</ul>
|
||||
<h4>2.0.0</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>
|
||||
Product Variants and Product Versions are here!<br/>
|
||||
Examples added.<br/>
|
||||
2kb Amazon Network for products fast sync<br/>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>1.2.0</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>
|
||||
Usability changes:<br/>
|
||||
Delay between requests option added to reduce Amazon API warnings<br/>
|
||||
Last cron run label on dashboard added<br/>
|
||||
<br/><br/>
|
||||
Programming changes:<br/>
|
||||
Many hooks added<br/>
|
||||
Default no item image accepts attributes<br/>
|
||||
Similar Products warning fixed
|
||||
</li>
|
||||
</ul>
|
||||
<h4>1.1.8</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Bug fix - Mobile layout for listing.</li>
|
||||
</ul>
|
||||
<h4>1.1.6, 1.1.7</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Bugs fixing</li>
|
||||
</ul>
|
||||
<h4>1.1.5</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>New Option - delete product(post) on quantity = 0</li>
|
||||
<li>New Action - Delete All Products That Have post_status = pending And KbAmzOfferSummary.TotalNew <= 0'</li>
|
||||
<li>Added Default Product Image in the listings.</li>
|
||||
<li>Added Popover on checkout button: if product is not sellable with the affiliate program, direct product link will be provided.</li>
|
||||
<li>Added Plugin Experience Program (Optional)</li>
|
||||
</ul>
|
||||
<h4>1.1.4</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Fixed bug when listing products with no quantity left. kb_amz_list_products now lists only products (posts) with post_status = publish be default, which can be changed.</li>
|
||||
</ul>
|
||||
<h4>1.1.3</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Fixed bug for creating multiple checkout pages.</li>
|
||||
<li>Fixed bug with listing price option. Now showing listing price and discounted price.</li>
|
||||
<li>Admin widgets css update.</li>
|
||||
<li><a href="?page=kbAmz&kbAction=info">Documentation</a> added.</li>
|
||||
</ul>
|
||||
<h4>1.1.2</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Listing price add when 'Show the original price of the product.' options is enabled.</li>
|
||||
<li>Disabled store widgets filters on product post page.</li>
|
||||
</ul>
|
||||
<h4>1.1.1</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Amazon Iframe Reviews added. You can test and provide feedback to complete this functionality.</li>
|
||||
<li>Fixed bug when using product images directly from Amazon and not displaying outside the product page. Thanks to alamandeh for reporting it.</li>
|
||||
<li>Fixed bug when pagination is disabled for one listing on multiple product listings.</li>
|
||||
<li>Fixed admin import search form same parameters after submit bug.</li>
|
||||
<li>Fixed bug for custom themes when having thumbnail size (class) on the listing page.</li>
|
||||
</ul>
|
||||
<h4>1.1.0</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Import timeout increased from default 30sec. to 90 sec.</li>
|
||||
<li>Added pagination on the <a href="?page=kbAmz&kbAction=importBySearch">search page</a>.</li>
|
||||
</ul>
|
||||
<h4>1.0.9</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>kb_amz_list_products shortcode accept short code parameters with php code. Ex. [kb_amz_list_products attribute_value="<? date('Y-m-d', time() - 3600); ?>"].</li>
|
||||
</ul>
|
||||
<h4>1.0.8</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>India is added to the import categories list thanks to Mr.Parmar.</li>
|
||||
</ul>
|
||||
<h4>1.0.7</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Short Codes bug fixed - all shortcodes use '_' instead of '-'.</li>
|
||||
<li>Added option for featured content in [kb_amz_list_products featured="Yes" featured_content_length="150"]. Content is loaded from the_excerpt or the product description.</li>
|
||||
<li>Bug fixed when using [kb_amz_list_products] in product shortcode content. (product is excluded from the query).</li>
|
||||
</ul>
|
||||
<h4>1.0.6</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Category accept functions in [kb_amz_list_products] and items_per_row added.</li>
|
||||
<li>Dashboard published products message added.</li>
|
||||
</ul>
|
||||
<h4>1.0.5</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Category fix in [kb_amz_list_products]</li>
|
||||
</ul>
|
||||
<h4>1.0.4</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Some bugs got fixed. Thank you for your support.</li>
|
||||
</ul>
|
||||
<h4>1.0.3</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>New Option = Download Images. This option allows you to store only the link of product`s images. This will save you space and time to import.</li>
|
||||
<li>Maintenance fixes.</li>
|
||||
<li>lib/KbAmazonImage</li>
|
||||
<li>lib/KbAmazonImages</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<h4>1.0.2</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Dashboard info update - products counts, products to download, products to sync, time to sync.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<h4>1.0.1</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>Front scripts are no longer loaded in admin.</li>
|
||||
<li>Products -> Short Codes, restore default content shortcodes. Option to replace content shortcode with the product content insuring better SEO and editability.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<h4>1.0.0</h4>
|
||||
<ul style="list-style-type: disc;">
|
||||
<li>First public version of the plugin</li>
|
||||
<li>Import products by amazon - ASIN, Search, Url Import (beta)</li>
|
||||
<li>Product attributes management and attributes restriction</li>
|
||||
<li>All products short codes management</li>
|
||||
<li>Cron job for similar products import and price update</li>
|
||||
<li><a href="?page=kbAmz&kbAction=productsShortCodes">Shortcodes</a></li>
|
||||
<li>Widgets for products filtering - Slider and Attributes filter</li>
|
||||
<li>Automatic products growing. Using similar products, this plugin will download products without you need to do anything.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
13
spec/fixtures/dynamic_finders/plugin_version/360-image/composer_file/package.json
vendored
Normal file
13
spec/fixtures/dynamic_finders/plugin_version/360-image/composer_file/package.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "algori-360-image-cgb-guten-block",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "cgb-scripts start",
|
||||
"build": "cgb-scripts build",
|
||||
"eject": "cgb-scripts eject"
|
||||
},
|
||||
"dependencies": {
|
||||
"cgb-scripts": "1.9.8"
|
||||
}
|
||||
}
|
||||
13
spec/fixtures/dynamic_finders/plugin_version/360-video/composer_file/package.json
vendored
Normal file
13
spec/fixtures/dynamic_finders/plugin_version/360-video/composer_file/package.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "algori-360-video-cgb-guten-block",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "cgb-scripts start",
|
||||
"build": "cgb-scripts build",
|
||||
"eject": "cgb-scripts eject"
|
||||
},
|
||||
"dependencies": {
|
||||
"cgb-scripts": "1.9.8"
|
||||
}
|
||||
}
|
||||
45
spec/fixtures/dynamic_finders/plugin_version/404-solution/composer_file/package.json
vendored
Normal file
45
spec/fixtures/dynamic_finders/plugin_version/404-solution/composer_file/package.json
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "404-solution",
|
||||
"version": "2.5.4",
|
||||
"description": "The 404 Solution Plugin.",
|
||||
"main": "Gulpfile.js",
|
||||
"dependencies": {
|
||||
"autoprefixer": "^6.3.1",
|
||||
"css-mqpacker": "^4.0.0",
|
||||
"del": "^2.2.0",
|
||||
"glob": "^6.0.4",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-cheerio": "^0.6.2",
|
||||
"gulp-concat": "^2.6.0",
|
||||
"gulp-cssnano": "^2.1.0",
|
||||
"gulp-imagemin": "^2.4.0",
|
||||
"gulp-notify": "^2.2.0",
|
||||
"gulp-plumber": "^1.1.0",
|
||||
"gulp-postcss": "^6.1.0",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-sass": "^2.2.0",
|
||||
"gulp-sass-lint": "^1.1.1",
|
||||
"gulp-sort": "^1.1.1",
|
||||
"gulp-sourcemaps": "^1.6.0",
|
||||
"gulp-uglify": "^1.5.2",
|
||||
"gulp-util": "^3.0.7",
|
||||
"gulp-wp-pot": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"scripts": {
|
||||
"test": "echo \"No test specified\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+thtps://github.com/aaron13100/404solution"
|
||||
},
|
||||
"keywords": [
|
||||
"plugin"
|
||||
],
|
||||
"author": "Aaron J",
|
||||
"license": "GPL-3.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/aaron13100/404solution/issues"
|
||||
},
|
||||
"homepage": "https://github.com/aaron13100/404solution"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: LayerSlider WP v4.5.5\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: 2013-06-26 22:23:20+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
@@ -0,0 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: LayerSlider WP 5.2.0\n"
|
||||
"POT-Creation-Date: 2014-08-15 00:06+0100\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "abovethefold",
|
||||
"version": "2.9.2",
|
||||
"description": "Above The Fold Optimization",
|
||||
"author": {
|
||||
"name": "info@pagespeed.pro",
|
||||
"email": "info@pagespeed.pro",
|
||||
"web": "pagespeed.pro"
|
||||
},
|
||||
"engines": {
|
||||
"node": "~0.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"jquery": "^3.1.1",
|
||||
"jsoneditor": "5.9.5",
|
||||
"lazyloadxt": "1.1.0",
|
||||
"webfontloader": "^1.6.28"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "latest",
|
||||
"grunt-closure-compiler": "latest",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-cssmin": "latest",
|
||||
"grunt-contrib-uglify": "latest",
|
||||
"matchdep": "latest",
|
||||
"merge": "^1.2.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,808 @@
|
||||
# Copyright (C) 2018 Academic Blogger's Toolkit 4.13.0
|
||||
# This file is distributed under the same license as the Academic Blogger's Toolkit 4.13.0 package.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Academic Blogger's Toolkit 4.13.0\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language-Team: Derek P Sifford <dereksifford@gmail.com>\n"
|
||||
"Last-Translator: Derek P Sifford <dereksifford@gmail.com>\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/dsifford/academic-bloggers-toolkit/issues\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: academic-bloggers-toolkit.php:100
|
||||
msgid "Plugin Settings"
|
||||
msgstr ""
|
||||
|
||||
#: academic-bloggers-toolkit.php:117
|
||||
msgid "Donate"
|
||||
msgstr ""
|
||||
|
||||
#: php/class-backend.php:72
|
||||
msgid "Notice"
|
||||
msgstr ""
|
||||
|
||||
#: php/class-backend.php:73
|
||||
msgid "Rich editing must be enabled to use the Academic Blogger's Toolkit plugin"
|
||||
msgstr ""
|
||||
|
||||
#: php/class-backend.php:131
|
||||
msgid "Reference List"
|
||||
msgstr ""
|
||||
|
||||
#: php/class-options.php:71, php/class-options.php:138
|
||||
msgid "Academic Blogger's Toolkit Options"
|
||||
msgstr ""
|
||||
|
||||
#: php/class-options.php:72
|
||||
msgid "Academic Blogger's Toolkit"
|
||||
msgstr ""
|
||||
|
||||
#: php/class-options.php:84
|
||||
msgid "You do not have sufficient permissions to access this page."
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:16, php/i18n.php:49
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:20, php/fieldmaps.php:74, php/fieldmaps.php:258, php/fieldmaps.php:352, php/fieldmaps.php:398, php/fieldmaps.php:488, php/fieldmaps.php:554, php/fieldmaps.php:591, php/fieldmaps.php:653, php/fieldmaps.php:717, php/fieldmaps.php:775, php/fieldmaps.php:826, php/fieldmaps.php:894, php/fieldmaps.php:941
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:25
|
||||
msgid "Bill Number"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:29
|
||||
msgid "Code Pages"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:31, php/fieldmaps.php:209, php/fieldmaps.php:447, php/fieldmaps.php:618, php/fieldmaps.php:672, php/fieldmaps.php:734, php/fieldmaps.php:792, php/fieldmaps.php:853, php/fieldmaps.php:912
|
||||
msgid "Number or Range of Numbers (100-200)"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:35
|
||||
msgid "Code Volume"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:37, php/fieldmaps.php:85, php/fieldmaps.php:91, php/fieldmaps.php:97, php/fieldmaps.php:103, php/fieldmaps.php:165, php/fieldmaps.php:175, php/fieldmaps.php:181, php/fieldmaps.php:187, php/fieldmaps.php:193, php/fieldmaps.php:269, php/fieldmaps.php:414, php/fieldmaps.php:420, php/fieldmaps.php:426, php/fieldmaps.php:432, php/fieldmaps.php:607, php/fieldmaps.php:665, php/fieldmaps.php:833, php/fieldmaps.php:901, php/fieldmaps.php:948
|
||||
msgid "One or more numbers, no spaces"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:41, php/fieldmaps.php:727, php/fieldmaps.php:905
|
||||
msgid "Section"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:45
|
||||
msgid "Legislative Body"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:49, php/fieldmaps.php:116, php/fieldmaps.php:217, php/fieldmaps.php:282, php/fieldmaps.php:327, php/fieldmaps.php:367, php/fieldmaps.php:451, php/fieldmaps.php:509, php/fieldmaps.php:572, php/fieldmaps.php:630, php/fieldmaps.php:688, php/fieldmaps.php:746, php/fieldmaps.php:801, php/fieldmaps.php:861, php/fieldmaps.php:916, php/fieldmaps.php:961, php/fieldmaps.php:1001
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:52, php/fieldmaps.php:58, php/fieldmaps.php:119, php/fieldmaps.php:125, php/fieldmaps.php:220, php/fieldmaps.php:226, php/fieldmaps.php:285, php/fieldmaps.php:291, php/fieldmaps.php:330, php/fieldmaps.php:336, php/fieldmaps.php:370, php/fieldmaps.php:454, php/fieldmaps.php:460, php/fieldmaps.php:512, php/fieldmaps.php:518, php/fieldmaps.php:575, php/fieldmaps.php:633, php/fieldmaps.php:691, php/fieldmaps.php:697, php/fieldmaps.php:749, php/fieldmaps.php:755, php/fieldmaps.php:804, php/fieldmaps.php:810, php/fieldmaps.php:864, php/fieldmaps.php:870, php/fieldmaps.php:919, php/fieldmaps.php:925, php/fieldmaps.php:964, php/fieldmaps.php:970, php/fieldmaps.php:1003, php/fieldmaps.php:1009
|
||||
msgid "YYYY/MM/DD or YYYY/MM or YYYY"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:56, php/fieldmaps.php:123, php/fieldmaps.php:224, php/fieldmaps.php:289, php/fieldmaps.php:334, php/fieldmaps.php:458, php/fieldmaps.php:516, php/fieldmaps.php:695, php/fieldmaps.php:753, php/fieldmaps.php:808, php/fieldmaps.php:868, php/fieldmaps.php:923, php/fieldmaps.php:968, php/fieldmaps.php:1007
|
||||
msgid "Date Accessed"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:64
|
||||
msgid "Sponsor"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:70, php/i18n.php:53
|
||||
msgid "Book"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:79
|
||||
msgid "Series Title"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:83, php/fieldmaps.php:173, php/fieldmaps.php:412
|
||||
msgid "Series Number"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:89, php/fieldmaps.php:946
|
||||
msgid "# of Pages"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:95, php/fieldmaps.php:179, php/fieldmaps.php:418, php/fieldmaps.php:605, php/fieldmaps.php:663
|
||||
msgid "Volume"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:101, php/fieldmaps.php:191, php/fieldmaps.php:430
|
||||
msgid "Edition"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:107, php/fieldmaps.php:197, php/fieldmaps.php:436, php/fieldmaps.php:845
|
||||
msgid "Publisher"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:112, php/fieldmaps.php:202, php/fieldmaps.php:440
|
||||
msgid "Publisher Location"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:131, php/fieldmaps.php:342, php/fieldmaps.php:376, php/fieldmaps.php:466, php/fieldmaps.php:639, php/fieldmaps.php:703, php/fieldmaps.php:761, php/fieldmaps.php:876, php/fieldmaps.php:931, php/fieldmaps.php:976, php/fieldmaps.php:1015
|
||||
msgid "Author"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:135, php/fieldmaps.php:240, php/fieldmaps.php:380, php/fieldmaps.php:470, php/fieldmaps.php:643, php/fieldmaps.php:707, php/fieldmaps.php:765
|
||||
msgid "Editor"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:139, php/fieldmaps.php:244, php/fieldmaps.php:384, php/fieldmaps.php:474, php/fieldmaps.php:880
|
||||
msgid "Series Editor"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:143, php/fieldmaps.php:248, php/fieldmaps.php:388, php/fieldmaps.php:478, php/fieldmaps.php:884
|
||||
msgid "Translator"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:149, php/i18n.php:57
|
||||
msgid "Book Section"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:153
|
||||
msgid "Section Title"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:158
|
||||
msgid "Book Title"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:163
|
||||
msgid "Chapter Number"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:169, php/fieldmaps.php:408, php/fieldmaps.php:837
|
||||
msgid "Series"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:185, php/fieldmaps.php:424
|
||||
msgid "# of Volumes"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:206, php/fieldmaps.php:444, php/fieldmaps.php:616, php/fieldmaps.php:669, php/fieldmaps.php:731, php/fieldmaps.php:790, php/fieldmaps.php:850, php/fieldmaps.php:909
|
||||
msgid "Pages"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:213, php/i18n.php:205
|
||||
msgid "ISBN"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:232
|
||||
msgid "Section Author"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:236
|
||||
msgid "Book Author"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:254
|
||||
msgid "Broadcast"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:262
|
||||
msgid "Program Title"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:267
|
||||
msgid "Episode Number"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:273, php/fieldmaps.php:505
|
||||
msgid "Format"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:277
|
||||
msgid "Network"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:297, php/fieldmaps.php:532
|
||||
msgid "Producer"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:301, php/fieldmaps.php:528
|
||||
msgid "Director"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:307, php/i18n.php:61
|
||||
msgid "Case"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:311
|
||||
msgid "Case Name"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:316
|
||||
msgid "Court"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:321
|
||||
msgid "Docket Number"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:323
|
||||
msgid "Any combination of non-whitespace characters"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:348, php/i18n.php:65
|
||||
msgid "Conference Proceeding"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:357
|
||||
msgid "Conference Name"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:362
|
||||
msgid "Conference Location"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:394, php/i18n.php:69
|
||||
msgid "Encyclopedia Entry"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:403
|
||||
msgid "Encyclopedia Title"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:484, php/i18n.php:73
|
||||
msgid "Film"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:493
|
||||
msgid "Distributor"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:497
|
||||
msgid "Genre"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:501, php/fieldmaps.php:568
|
||||
msgid "Language"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:524
|
||||
msgid "Scriptwriter"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:538, php/i18n.php:77
|
||||
msgid "Generic (Note)"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:542
|
||||
msgid "Text"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:550
|
||||
msgid "Presentation"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:559
|
||||
msgid "Event Name"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:564
|
||||
msgid "Event Location"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:581
|
||||
msgid "Presenter"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:587, php/i18n.php:85
|
||||
msgid "Journal Article"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:596
|
||||
msgid "Journal"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:601
|
||||
msgid "Journal Abbreviation"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:611, php/fieldmaps.php:676, php/fieldmaps.php:738
|
||||
msgid "Issue"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:622
|
||||
msgid "DOI"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:626, php/fieldmaps.php:684, php/fieldmaps.php:742, php/fieldmaps.php:857, php/fieldmaps.php:996, php/i18n.php:207
|
||||
msgid "URL"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:649, php/i18n.php:89
|
||||
msgid "Magazine Article"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:658
|
||||
msgid "Magazine"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:680
|
||||
msgid "ISSN"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:713, php/i18n.php:93
|
||||
msgid "Newspaper Article"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:722, php/fieldmaps.php:841
|
||||
msgid "Publication"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:771, php/i18n.php:97
|
||||
msgid "Patent"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:780, php/fieldmaps.php:831
|
||||
msgid "Number"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:785
|
||||
msgid "Jurisdiction"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:796
|
||||
msgid "Issuer"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:816
|
||||
msgid "Inventor"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:822, php/i18n.php:101
|
||||
msgid "Report"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:890, php/i18n.php:105
|
||||
msgid "Statute"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:899
|
||||
msgid "Statute Number"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:937, php/i18n.php:109
|
||||
msgid "Thesis"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:952
|
||||
msgid "University"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:957
|
||||
msgid "Location"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:982, php/i18n.php:117
|
||||
msgid "Web Page"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:986
|
||||
msgid "Content Title"
|
||||
msgstr ""
|
||||
|
||||
#: php/fieldmaps.php:991
|
||||
msgid "Website Title"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:81
|
||||
msgid "Hearing"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:113
|
||||
msgid "Television Broadcast"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:125, php/views/options-page.php:237
|
||||
msgid "Footnotes"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:126
|
||||
msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:132
|
||||
msgid "Your WordPress PHP installation is incomplete. You must have the following PHP extensions enabled to use this feature: %s"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:135
|
||||
msgid "Request not valid"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:136
|
||||
msgid "Site denied request"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:137
|
||||
msgid "Invalid file extension. Extension must be .ris, .bib, or .bibtex"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:138
|
||||
msgid "The selected file could not be processed"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:140
|
||||
msgid "No identifiers could be found for your request"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:141
|
||||
msgid "The following identifiers could not be found"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:143
|
||||
msgid "Network Error"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:144
|
||||
msgid "Your search returned 0 results"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:145
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:146
|
||||
msgid "The following references were unable to be processed"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:147
|
||||
msgid "Request returned a non-200 status code"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:149
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:150
|
||||
msgid "Reason"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:151
|
||||
msgid "No bibliography format exists for your citation type"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:154
|
||||
msgid "An unexpected error occurred"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:157
|
||||
msgid "Please report this error, including the steps taken to trigger it, here: %s"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:161
|
||||
msgid "TinyMCE editor doesn't appear to be available in this scope"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:162
|
||||
msgid "Invalid predefined style type"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:168
|
||||
msgid "Custom Style"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:169
|
||||
msgid "Pre-defined Styles"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:171
|
||||
msgid "Toggle menu"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:173
|
||||
msgid "Delete all references"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:174
|
||||
msgid "Usage instructions"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:175
|
||||
msgid "Import references"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:176
|
||||
msgid "Refresh reference list"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:177
|
||||
msgid "Insert static publication list"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:180
|
||||
msgid "Cited Items"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:182
|
||||
msgid "Add reference"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:183
|
||||
msgid "Insert selected references"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:184
|
||||
msgid "Pin reference list"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:185
|
||||
msgid "Remove selected references"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:187
|
||||
msgid "Uncited Items"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:193
|
||||
msgid "Add Manually"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:194
|
||||
msgid "Add Reference"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:195
|
||||
msgid "Add with Identifier"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:196
|
||||
msgid "Insert citation inline"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:197, php/i18n.php:237
|
||||
msgid "Search PubMed"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:200
|
||||
msgid "DOI/PMID/PMCID"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:203
|
||||
msgid "Autocite"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:204
|
||||
msgid "Citation Type"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:206, php/i18n.php:236
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:210
|
||||
msgid "Add contributor"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:211
|
||||
msgid "Contributors"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:214
|
||||
msgid "Given Name, M.I."
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:215
|
||||
msgid "Surname"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:216
|
||||
msgid "Literal Name"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:217
|
||||
msgid "Remove contributor"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:218
|
||||
msgid "Toggle literal name"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:220
|
||||
msgid "Add References"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:222
|
||||
msgid "Close dialog"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:224
|
||||
msgid "Edit Reference"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:225
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:228
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:229
|
||||
msgid "Import References"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:230
|
||||
msgid "Choose File"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:233
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:234
|
||||
msgid "Next"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:235
|
||||
msgid "Previous"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:238
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:243
|
||||
msgid "Citation Style Type"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:244
|
||||
msgid "Predefined"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:245
|
||||
msgid "Custom"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:246
|
||||
msgid "Heading"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:247
|
||||
msgid "Heading Level"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:248
|
||||
msgid "Fixed"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:249
|
||||
msgid "Toggle"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:250
|
||||
msgid "Bibliography Style"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:252
|
||||
msgid "Link Format"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:253
|
||||
msgid "Make URLs clickable and always add trailing source link"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:254
|
||||
msgid "Make entire reference a clickable link to the source URL"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:255
|
||||
msgid "Make URLs clickable only"
|
||||
msgstr ""
|
||||
|
||||
#: php/i18n.php:256
|
||||
msgid "Never add clickable links"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:3
|
||||
msgid "Please send your feedback!"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:9
|
||||
msgid "If you experience a bug or would like to request a new feature, please visit the <a href=\"%s\">GitHub Repository</a> and submit an issue."
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:24
|
||||
msgid "Plugin Requirements Check"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:29
|
||||
msgid "PHP Version"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:36
|
||||
msgid "PHP version should be at least 7.0"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:47, php/views/options-page.php:94
|
||||
msgid "PHP %s Extension"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:59, php/views/options-page.php:106
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:61, php/views/options-page.php:108
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:71, php/views/options-page.php:118
|
||||
msgid "The %s PHP extension is required for some plugin features."
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:81, php/views/options-page.php:128
|
||||
msgid "Click here for installation instructions"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:135
|
||||
msgid "Recommended Browsers"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:138
|
||||
msgid "Google Chrome, Mozilla Firefox, Apple Safari, or Microsoft Edge."
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:147
|
||||
msgid "Note: Be sure that your server does not have %1$s or %2$s configured in your php.ini file or .htaccess file. Both can cause issues."
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:164
|
||||
msgid "Default Citation Style"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:170, php/views/options-page.php:187, php/views/options-page.php:251
|
||||
msgid "Update"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:181
|
||||
msgid "Display Options"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:198
|
||||
msgid "Override CSS"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:203
|
||||
msgid "CSS Selectors used by this plugin"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:205
|
||||
msgid "Inline Citations"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:213
|
||||
msgid "Citation Tooltips"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:221
|
||||
msgid "Bibliography"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:229
|
||||
msgid "Static Publication Lists"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:260
|
||||
msgid "How do I"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:264
|
||||
msgid "Make my tooltips a different color?"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:278
|
||||
msgid "Apply style to the bibliography list?"
|
||||
msgstr ""
|
||||
|
||||
#: php/views/options-page.php:292
|
||||
msgid "Apply style to the inline citations"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,562 @@
|
||||
# Copyright (C) 2018 ThemeEgg
|
||||
# This file is distributed under the GPL-2.0+.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Accordion for WordPress 1.1.3\n"
|
||||
"Report-Msgid-Bugs-To: themeeggofficial@gmail.com\n"
|
||||
"POT-Creation-Date: 2018-02-24 04:16:52+00:00\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"PO-Revision-Date: 2018-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
|
||||
"X-Generator: grunt-wp-i18n1.0.0\n"
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:66
|
||||
#: includes/class-afwp-accordion-post-type.php:109
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:66
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:109
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:66
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:109
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:66
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:109
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:66
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:109
|
||||
msgid "Accordion template"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:79
|
||||
#: includes/class-afwp-accordion-post-type.php:128
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:79
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:128
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:79
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:128
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:79
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:128
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:79
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:128
|
||||
msgid "Select template for accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:82
|
||||
#: includes/class-afwp-accordion-post-type.php:133
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:82
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:133
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:82
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:133
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:82
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:133
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:82
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:133
|
||||
msgid "Accordion style"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:93
|
||||
#: includes/class-afwp-accordion-post-type.php:151
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:93
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:151
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:93
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:151
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:93
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:151
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:93
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:151
|
||||
msgid "Select style for accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:190
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:190
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:190
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:190
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:190
|
||||
msgid "Shortcode"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:203
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:203
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:203
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:203
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:203
|
||||
msgid "Search accordion group"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:204
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:204
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:204
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:204
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:204
|
||||
msgid "All Accordion groups"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:205
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:205
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:205
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:205
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:205
|
||||
msgid "Parent Accordion group"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:206
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:206
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:206
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:206
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:206
|
||||
msgid "Parent Accordion group:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:207
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:207
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:207
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:207
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:207
|
||||
msgid "Edit Accordion group"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:208
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:208
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:208
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:208
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:208
|
||||
msgid "Update Accordion group"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:209
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:209
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:209
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:209
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:209
|
||||
msgid "Add New Accordion group"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:210
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:210
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:210
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:210
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:210
|
||||
msgid "New Accordion group Name"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:211
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:211
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:211
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:211
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:211
|
||||
msgid "Accordion group"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:232
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:232
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:232
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:232
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:232
|
||||
msgid "Add New Accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:233
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:233
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:233
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:233
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:233
|
||||
msgid "New Accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:234
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:234
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:234
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:234
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:234
|
||||
msgid "Edit Accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:235
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:235
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:235
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:235
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:235
|
||||
msgid "View Accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:236
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:236
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:236
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:236
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:236
|
||||
msgid "All Accordions"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:237
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:237
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:237
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:237
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:237
|
||||
msgid "Search Accordions"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:238
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:238
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:238
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:238
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:238
|
||||
msgid "Parent Accordions:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:239
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:239
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:239
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:239
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:239
|
||||
msgid "No accordions found."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:240
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:240
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:240
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:240
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:240
|
||||
msgid "No accordions found in Trash."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:245
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:245
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:245
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:245
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:245
|
||||
msgid "Description."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-widget.php:28
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-accordion-widget.php:23
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-widget.php:28
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-widget.php:28
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-widget.php:28
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-widget.php:28
|
||||
msgid "Widget for Accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-widget.php:32
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-accordion-widget.php:27
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-widget.php:32
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-widget.php:32
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-widget.php:32
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-widget.php:32
|
||||
msgid "Accordion Post Widget"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-widget.php:150
|
||||
#: includes/class-afwp-nav-menu-accordion-widget.php:183
|
||||
#: includes/class-afwp-term-accordion-widget.php:143
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-accordion-widget.php:134
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-nav-menu-accordion-widget.php:168
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-term-accordion-widget.php:138
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-widget.php:150
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-nav-menu-accordion-widget.php:183
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-term-accordion-widget.php:143
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-widget.php:150
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-nav-menu-accordion-widget.php:183
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-term-accordion-widget.php:143
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-widget.php:150
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-nav-menu-accordion-widget.php:183
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-term-accordion-widget.php:143
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-widget.php:150
|
||||
#: svn-production/trunk/includes/class-afwp-nav-menu-accordion-widget.php:183
|
||||
#: svn-production/trunk/includes/class-afwp-term-accordion-widget.php:143
|
||||
msgid "Title:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-widget.php:156
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-accordion-widget.php:137
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-widget.php:156
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-widget.php:156
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-widget.php:156
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-widget.php:156
|
||||
msgid "Post Type:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-widget.php:175
|
||||
#: includes/class-afwp-term-accordion-widget.php:148
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-accordion-widget.php:150
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-term-accordion-widget.php:143
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-widget.php:175
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-term-accordion-widget.php:148
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-widget.php:175
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-term-accordion-widget.php:148
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-widget.php:175
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-term-accordion-widget.php:148
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-widget.php:175
|
||||
#: svn-production/trunk/includes/class-afwp-term-accordion-widget.php:148
|
||||
msgid "Taxonomy:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-widget.php:191
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-accordion-widget.php:161
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-widget.php:191
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-widget.php:191
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-widget.php:191
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-widget.php:191
|
||||
msgid "Term:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-widget.php:211
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-accordion-widget.php:177
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-widget.php:211
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-widget.php:211
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-widget.php:211
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-widget.php:211
|
||||
msgid "Show no of post:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-widget.php:217
|
||||
#: includes/class-afwp-nav-menu-accordion-widget.php:213
|
||||
#: includes/class-afwp-term-accordion-widget.php:173
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-accordion-widget.php:180
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-nav-menu-accordion-widget.php:193
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-term-accordion-widget.php:166
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-widget.php:217
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-nav-menu-accordion-widget.php:213
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-term-accordion-widget.php:173
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-widget.php:217
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-nav-menu-accordion-widget.php:213
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-term-accordion-widget.php:173
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-widget.php:217
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-nav-menu-accordion-widget.php:213
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-term-accordion-widget.php:173
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-widget.php:217
|
||||
#: svn-production/trunk/includes/class-afwp-nav-menu-accordion-widget.php:213
|
||||
#: svn-production/trunk/includes/class-afwp-term-accordion-widget.php:173
|
||||
msgid "Template:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-widget.php:229
|
||||
#: includes/class-afwp-nav-menu-accordion-widget.php:227
|
||||
#: includes/class-afwp-term-accordion-widget.php:186
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-accordion-widget.php:192
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-nav-menu-accordion-widget.php:207
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-term-accordion-widget.php:181
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-widget.php:229
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-nav-menu-accordion-widget.php:227
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-term-accordion-widget.php:186
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-widget.php:229
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-nav-menu-accordion-widget.php:227
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-term-accordion-widget.php:186
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-widget.php:229
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-nav-menu-accordion-widget.php:227
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-term-accordion-widget.php:186
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-widget.php:229
|
||||
#: svn-production/trunk/includes/class-afwp-nav-menu-accordion-widget.php:227
|
||||
#: svn-production/trunk/includes/class-afwp-term-accordion-widget.php:186
|
||||
msgid "Style:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-nav-menu-accordion-widget.php:32
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-nav-menu-accordion-widget.php:27
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-nav-menu-accordion-widget.php:32
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-nav-menu-accordion-widget.php:32
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-nav-menu-accordion-widget.php:32
|
||||
#: svn-production/trunk/includes/class-afwp-nav-menu-accordion-widget.php:32
|
||||
msgid "Add a custom accordion menu to your sidebar."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-nav-menu-accordion-widget.php:35
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-nav-menu-accordion-widget.php:30
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-nav-menu-accordion-widget.php:35
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-nav-menu-accordion-widget.php:35
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-nav-menu-accordion-widget.php:35
|
||||
#: svn-production/trunk/includes/class-afwp-nav-menu-accordion-widget.php:35
|
||||
msgid "Accordion Menu"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-nav-menu-accordion-widget.php:176
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-nav-menu-accordion-widget.php:164
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-nav-menu-accordion-widget.php:176
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-nav-menu-accordion-widget.php:176
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-nav-menu-accordion-widget.php:176
|
||||
#: svn-production/trunk/includes/class-afwp-nav-menu-accordion-widget.php:176
|
||||
msgid "No menus have been created yet. <a href=\"%s\">Create some</a>."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-nav-menu-accordion-widget.php:190
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-nav-menu-accordion-widget.php:172
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-nav-menu-accordion-widget.php:190
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-nav-menu-accordion-widget.php:190
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-nav-menu-accordion-widget.php:190
|
||||
#: svn-production/trunk/includes/class-afwp-nav-menu-accordion-widget.php:190
|
||||
msgid "Select Menu:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-nav-menu-accordion-widget.php:193
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-nav-menu-accordion-widget.php:174
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-nav-menu-accordion-widget.php:193
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-nav-menu-accordion-widget.php:193
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-nav-menu-accordion-widget.php:193
|
||||
#: svn-production/trunk/includes/class-afwp-nav-menu-accordion-widget.php:193
|
||||
msgid "— Select —"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-nav-menu-accordion-widget.php:206
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-nav-menu-accordion-widget.php:184
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-nav-menu-accordion-widget.php:206
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-nav-menu-accordion-widget.php:206
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-nav-menu-accordion-widget.php:206
|
||||
#: svn-production/trunk/includes/class-afwp-nav-menu-accordion-widget.php:206
|
||||
msgid "Show as Accordion:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-nav-menu-accordion-widget.php:240
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-nav-menu-accordion-widget.php:216
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-nav-menu-accordion-widget.php:240
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-nav-menu-accordion-widget.php:240
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-nav-menu-accordion-widget.php:240
|
||||
#: svn-production/trunk/includes/class-afwp-nav-menu-accordion-widget.php:240
|
||||
msgid "Edit Menu"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-term-accordion-widget.php:28
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-term-accordion-widget.php:23
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-term-accordion-widget.php:28
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-term-accordion-widget.php:28
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-term-accordion-widget.php:28
|
||||
#: svn-production/trunk/includes/class-afwp-term-accordion-widget.php:28
|
||||
msgid "Widget for Term Accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-term-accordion-widget.php:32
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-term-accordion-widget.php:27
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-term-accordion-widget.php:32
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-term-accordion-widget.php:32
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-term-accordion-widget.php:32
|
||||
#: svn-production/trunk/includes/class-afwp-term-accordion-widget.php:32
|
||||
msgid "Accordion Term Widget"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-term-accordion-widget.php:167
|
||||
#: svn-production/tags/1.0.0/includes/class-afwp-term-accordion-widget.php:161
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-term-accordion-widget.php:167
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-term-accordion-widget.php:167
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-term-accordion-widget.php:167
|
||||
#: svn-production/trunk/includes/class-afwp-term-accordion-widget.php:167
|
||||
msgid "Show no of term:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/function-afwp-core.php:14
|
||||
#: svn-production/tags/1.1.0/includes/function-afwp-core.php:14
|
||||
#: svn-production/tags/1.1.1/includes/function-afwp-core.php:14
|
||||
#: svn-production/tags/1.1.2/includes/function-afwp-core.php:14
|
||||
#: svn-production/trunk/includes/function-afwp-core.php:14
|
||||
msgid "Default"
|
||||
msgstr ""
|
||||
|
||||
#: includes/function-afwp-core.php:15
|
||||
#: svn-production/tags/1.1.0/includes/function-afwp-core.php:15
|
||||
#: svn-production/tags/1.1.1/includes/function-afwp-core.php:15
|
||||
#: svn-production/tags/1.1.2/includes/function-afwp-core.php:15
|
||||
#: svn-production/trunk/includes/function-afwp-core.php:15
|
||||
msgid "Template 1"
|
||||
msgstr ""
|
||||
|
||||
#: includes/function-afwp-core.php:16
|
||||
#: svn-production/tags/1.1.2/includes/function-afwp-core.php:16
|
||||
#: svn-production/trunk/includes/function-afwp-core.php:16
|
||||
msgid "Theme default"
|
||||
msgstr ""
|
||||
|
||||
#: includes/function-afwp-core.php:26
|
||||
#: svn-production/tags/1.1.0/includes/function-afwp-core.php:25
|
||||
#: svn-production/tags/1.1.1/includes/function-afwp-core.php:25
|
||||
#: svn-production/tags/1.1.2/includes/function-afwp-core.php:26
|
||||
#: svn-production/trunk/includes/function-afwp-core.php:26
|
||||
msgid "Vertical"
|
||||
msgstr ""
|
||||
|
||||
#: includes/function-afwp-core.php:27
|
||||
#: svn-production/tags/1.1.0/includes/function-afwp-core.php:26
|
||||
#: svn-production/tags/1.1.1/includes/function-afwp-core.php:26
|
||||
#: svn-production/tags/1.1.2/includes/function-afwp-core.php:27
|
||||
#: svn-production/trunk/includes/function-afwp-core.php:27
|
||||
msgid "Horizontal"
|
||||
msgstr ""
|
||||
|
||||
#. Plugin Name of the plugin/theme
|
||||
msgid "Accordion for WordPress"
|
||||
msgstr ""
|
||||
|
||||
#. Plugin URI of the plugin/theme
|
||||
msgid "http://themeegg.com/plugins/accordion-for-wp/"
|
||||
msgstr ""
|
||||
|
||||
#. Description of the plugin/theme
|
||||
msgid ""
|
||||
"Accordion for wordpress widgets and shortcode plugin with multiple "
|
||||
"templates."
|
||||
msgstr ""
|
||||
|
||||
#. Author of the plugin/theme
|
||||
msgid "ThemeEgg"
|
||||
msgstr ""
|
||||
|
||||
#. Author URI of the plugin/theme
|
||||
msgid "http://themeegg.com/"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:201
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:201
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:201
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:201
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:201
|
||||
msgctxt "taxonomy general name"
|
||||
msgid "Accordion group"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:202
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:202
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:202
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:202
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:202
|
||||
msgctxt "taxonomy singular name"
|
||||
msgid "Accordion group"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:227
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:227
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:227
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:227
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:227
|
||||
msgctxt "post type general name"
|
||||
msgid "Accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:228
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:228
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:228
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:228
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:228
|
||||
msgctxt "post type singular name"
|
||||
msgid "Accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:229
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:229
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:229
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:229
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:229
|
||||
msgctxt "admin menu"
|
||||
msgid "Accordions"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:230
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:230
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:230
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:230
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:230
|
||||
msgctxt "add new on admin bar"
|
||||
msgid "Accordion"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-afwp-accordion-post-type.php:231
|
||||
#: svn-production/tags/1.1.0/includes/class-afwp-accordion-post-type.php:231
|
||||
#: svn-production/tags/1.1.1/includes/class-afwp-accordion-post-type.php:231
|
||||
#: svn-production/tags/1.1.2/includes/class-afwp-accordion-post-type.php:231
|
||||
#: svn-production/trunk/includes/class-afwp-accordion-post-type.php:231
|
||||
msgctxt "book"
|
||||
msgid "Add New"
|
||||
msgstr ""
|
||||
3407
spec/fixtures/dynamic_finders/plugin_version/acf-content-analysis-for-yoast-seo/composer_file/package-lock.json
generated
vendored
Normal file
3407
spec/fixtures/dynamic_finders/plugin_version/acf-content-analysis-for-yoast-seo/composer_file/package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,88 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: ACF Field Selector 4.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-04-21 23:13+0100\n"
|
||||
"PO-Revision-Date: 2015-04-21 23:13+0100\n"
|
||||
"Last-Translator: Daniel Pataki <contact@tastique.org>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Poedit-KeywordsList: __;_e\n"
|
||||
"X-Poedit-Basepath: .\n"
|
||||
"X-Poedit-SearchPath-0: ..\n"
|
||||
|
||||
#: ../acf-field_selector-v4.php:41 ../acf-field_selector-v5.php:38
|
||||
msgid "Field Selector"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:42 ../acf-field_selector-v5.php:39
|
||||
msgid "Choice"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:106 ../acf-field_selector-v5.php:93
|
||||
msgid "Group Filtering"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:107
|
||||
msgid "Enter group id numbers separated by commas to include or exclude them."
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:118 ../acf-field_selector-v4.php:154
|
||||
#: ../acf-field_selector-v5.php:99 ../acf-field_selector-v5.php:118
|
||||
msgid "Include"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:119 ../acf-field_selector-v4.php:155
|
||||
#: ../acf-field_selector-v5.php:100 ../acf-field_selector-v5.php:119
|
||||
msgid "Exclude"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:142 ../acf-field_selector-v5.php:112
|
||||
msgid "Type Filtering"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:143
|
||||
msgid "Enter type slugs separated by commas to include or exclude them."
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:196 ../acf-field_selector-v5.php:152
|
||||
msgid "Available Fields"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:197 ../acf-field_selector-v5.php:153
|
||||
msgid "Type to search..."
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:206 ../acf-field_selector-v5.php:162
|
||||
msgid "Selected Fields"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v4.php:207 ../acf-field_selector-v5.php:163
|
||||
msgid "Drag and drop to re-order your selection"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v5.php:94
|
||||
msgid "Set how the given groups are used"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v5.php:105
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v5.php:106
|
||||
msgid "Set the ID of groups to include or exclude"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v5.php:113
|
||||
msgid "Set how the given types are used"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v5.php:124
|
||||
msgid "Types"
|
||||
msgstr ""
|
||||
|
||||
#: ../acf-field_selector-v5.php:125
|
||||
msgid "Set the types to include or exclude"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,90 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: ACF Field Selector 4.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-04-21 23:13+0100\n"
|
||||
"PO-Revision-Date: 2015-04-21 23:13+0100\n"
|
||||
"Last-Translator: Daniel Pataki <contact@tastique.org>\n"
|
||||
"Language-Team: Daniel Pataki <hello@danielpataki.com>\n"
|
||||
"Language: Hungarian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Poedit-KeywordsList: __;_e\n"
|
||||
"X-Poedit-Basepath: .\n"
|
||||
"X-Poedit-SearchPath-0: ..\n"
|
||||
|
||||
#: ../acf-field_selector-v4.php:41 ../acf-field_selector-v5.php:38
|
||||
msgid "Field Selector"
|
||||
msgstr "Mező Választó"
|
||||
|
||||
#: ../acf-field_selector-v4.php:42 ../acf-field_selector-v5.php:39
|
||||
msgid "Choice"
|
||||
msgstr "Választás"
|
||||
|
||||
#: ../acf-field_selector-v4.php:106 ../acf-field_selector-v5.php:93
|
||||
msgid "Group Filtering"
|
||||
msgstr "Csoport Szűkítés"
|
||||
|
||||
#: ../acf-field_selector-v4.php:107
|
||||
msgid "Enter group id numbers separated by commas to include or exclude them."
|
||||
msgstr ""
|
||||
"A mezők szűlítéséhez adj meg csoport azonosítókat, vesszővel elválasztva"
|
||||
|
||||
#: ../acf-field_selector-v4.php:118 ../acf-field_selector-v4.php:154
|
||||
#: ../acf-field_selector-v5.php:99 ../acf-field_selector-v5.php:118
|
||||
msgid "Include"
|
||||
msgstr "Engedélyezés"
|
||||
|
||||
#: ../acf-field_selector-v4.php:119 ../acf-field_selector-v4.php:155
|
||||
#: ../acf-field_selector-v5.php:100 ../acf-field_selector-v5.php:119
|
||||
msgid "Exclude"
|
||||
msgstr "Titlás"
|
||||
|
||||
#: ../acf-field_selector-v4.php:142 ../acf-field_selector-v5.php:112
|
||||
msgid "Type Filtering"
|
||||
msgstr "Típus Szűkítés"
|
||||
|
||||
#: ../acf-field_selector-v4.php:143
|
||||
msgid "Enter type slugs separated by commas to include or exclude them."
|
||||
msgstr "A mezők szűkítéséhezt adj meg típus neveket, vesszővel elválasztva"
|
||||
|
||||
#: ../acf-field_selector-v4.php:196 ../acf-field_selector-v5.php:152
|
||||
msgid "Available Fields"
|
||||
msgstr "Választható Mezők"
|
||||
|
||||
#: ../acf-field_selector-v4.php:197 ../acf-field_selector-v5.php:153
|
||||
msgid "Type to search..."
|
||||
msgstr "Kereséshez kezdj el írni"
|
||||
|
||||
#: ../acf-field_selector-v4.php:206 ../acf-field_selector-v5.php:162
|
||||
msgid "Selected Fields"
|
||||
msgstr "Választott Mezők"
|
||||
|
||||
#: ../acf-field_selector-v4.php:207 ../acf-field_selector-v5.php:163
|
||||
msgid "Drag and drop to re-order your selection"
|
||||
msgstr "Kattints, húzd és engedd el a mezőt az átrendezéshez"
|
||||
|
||||
#: ../acf-field_selector-v5.php:94
|
||||
msgid "Set how the given groups are used"
|
||||
msgstr "Addm meg, hogyan szűkítsék a csoportok a listát"
|
||||
|
||||
#: ../acf-field_selector-v5.php:105
|
||||
msgid "Groups"
|
||||
msgstr "Csoportok"
|
||||
|
||||
#: ../acf-field_selector-v5.php:106
|
||||
msgid "Set the ID of groups to include or exclude"
|
||||
msgstr "Adj meg csoport azonosítókat engedélyezéshez vagy tiltáshoz"
|
||||
|
||||
#: ../acf-field_selector-v5.php:113
|
||||
msgid "Set how the given types are used"
|
||||
msgstr "Add meg, hogyan szűkítsék a típusok a listát"
|
||||
|
||||
#: ../acf-field_selector-v5.php:124
|
||||
msgid "Types"
|
||||
msgstr "Típusok"
|
||||
|
||||
#: ../acf-field_selector-v5.php:125
|
||||
msgid "Set the types to include or exclude"
|
||||
msgstr "Adj meg típusokat engedélyezéshez vagy tiltáshoz"
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user