Showing preview only (1,852K chars total). Download the full file or copy to clipboard to get everything.
Repository: google/tsunami-security-scanner
Branch: master
Commit: 32920de1868c
Files: 345
Total size: 1.7 MB
Directory structure:
gitextract_306kc4re/
├── .dockerignore
├── .gitattributes
├── .github/
│ └── workflows/
│ ├── core-build.yml
│ ├── core-push.yml
│ ├── devel-push.yml
│ └── full-push.yml
├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── common/
│ ├── README.md
│ ├── build.gradle
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── com/
│ │ └── google/
│ │ └── tsunami/
│ │ └── common/
│ │ ├── ErrorCode.java
│ │ ├── TsunamiException.java
│ │ ├── cli/
│ │ │ ├── CliOption.java
│ │ │ └── CliOptionsModule.java
│ │ ├── command/
│ │ │ ├── CommandExecutionThreadPool.java
│ │ │ ├── CommandExecutor.java
│ │ │ ├── CommandExecutorFactory.java
│ │ │ └── CommandExecutorModule.java
│ │ ├── concurrent/
│ │ │ ├── BaseThreadPoolModule.java
│ │ │ ├── ScheduledThreadPoolModule.java
│ │ │ └── ThreadPoolModule.java
│ │ ├── config/
│ │ │ ├── ConfigException.java
│ │ │ ├── ConfigLoader.java
│ │ │ ├── ConfigModule.java
│ │ │ ├── TsunamiConfig.java
│ │ │ ├── YamlConfigLoader.java
│ │ │ └── annotations/
│ │ │ └── ConfigProperties.java
│ │ ├── data/
│ │ │ ├── NetworkEndpointUtils.java
│ │ │ └── NetworkServiceUtils.java
│ │ ├── io/
│ │ │ └── archiving/
│ │ │ ├── Archiver.java
│ │ │ ├── GoogleCloudStorageArchiver.java
│ │ │ ├── GoogleCloudStorageArchiverModule.java
│ │ │ ├── RawFileArchiver.java
│ │ │ └── testing/
│ │ │ ├── FakeArchiver.java
│ │ │ ├── FakeGoogleCloudStorageArchivers.java
│ │ │ ├── FakeGoogleCloudStorageArchiversModule.java
│ │ │ ├── FakeRawFileArchiver.java
│ │ │ └── FakeRawFileArchiverModule.java
│ │ ├── net/
│ │ │ ├── FuzzingUtils.java
│ │ │ ├── UrlUtils.java
│ │ │ ├── db/
│ │ │ │ ├── ConnectionProvider.java
│ │ │ │ └── ConnectionProviderInterface.java
│ │ │ ├── http/
│ │ │ │ ├── HttpClient.java
│ │ │ │ ├── HttpClientCliOptions.java
│ │ │ │ ├── HttpClientConfigProperties.java
│ │ │ │ ├── HttpClientModule.java
│ │ │ │ ├── HttpHeaders.java
│ │ │ │ ├── HttpMethod.java
│ │ │ │ ├── HttpRequest.java
│ │ │ │ ├── HttpResponse.java
│ │ │ │ ├── HttpStatus.java
│ │ │ │ ├── OkHttpHttpClient.java
│ │ │ │ └── javanet/
│ │ │ │ ├── ConnectionFactory.java
│ │ │ │ └── DefaultConnectionFactory.java
│ │ │ └── socket/
│ │ │ ├── DefaultTsunamiSocketFactory.java
│ │ │ ├── TsunamiSocketFactory.java
│ │ │ ├── TsunamiSocketFactoryCliOptions.java
│ │ │ ├── TsunamiSocketFactoryConfigProperties.java
│ │ │ └── TsunamiSocketFactoryModule.java
│ │ ├── reflection/
│ │ │ ├── ClassGraphModule.java
│ │ │ └── RuntimeClassGraphScanResult.java
│ │ ├── server/
│ │ │ ├── CompactRunRequestHelper.java
│ │ │ └── LanguageServerCommand.java
│ │ ├── time/
│ │ │ ├── SystemUtcClockModule.java
│ │ │ ├── UtcClock.java
│ │ │ └── testing/
│ │ │ ├── FakeUtcClock.java
│ │ │ └── FakeUtcClockModule.java
│ │ └── version/
│ │ ├── ComparisonUtility.java
│ │ ├── KnownQualifier.java
│ │ ├── Segment.java
│ │ ├── Token.java
│ │ ├── Version.java
│ │ ├── VersionRange.java
│ │ └── VersionSet.java
│ └── test/
│ ├── java/
│ │ └── com/
│ │ └── google/
│ │ └── tsunami/
│ │ └── common/
│ │ ├── cli/
│ │ │ └── CliOptionsModuleTest.java
│ │ ├── command/
│ │ │ ├── CommandExecutorFactoryTest.java
│ │ │ └── CommandExecutorTest.java
│ │ ├── concurrent/
│ │ │ ├── BaseThreadPoolModuleTest.java
│ │ │ ├── ScheduledThreadPoolModuleTest.java
│ │ │ └── ThreadPoolModuleTest.java
│ │ ├── config/
│ │ │ ├── ConfigModuleTest.java
│ │ │ ├── TsunamiConfigTest.java
│ │ │ └── YamlConfigLoaderTest.java
│ │ ├── data/
│ │ │ ├── NetworkEndpointUtilsTest.java
│ │ │ └── NetworkServiceUtilsTest.java
│ │ ├── io/
│ │ │ └── archiving/
│ │ │ ├── ArchiverTestUtils.java
│ │ │ ├── GoogleCloudStorageArchiverTest.java
│ │ │ └── RawFileArchiverTest.java
│ │ ├── net/
│ │ │ ├── FuzzingUtilsTest.java
│ │ │ ├── UrlUtilsTest.java
│ │ │ ├── http/
│ │ │ │ ├── HttpClientModuleTest.java
│ │ │ │ ├── HttpHeadersTest.java
│ │ │ │ ├── HttpRequestTest.java
│ │ │ │ ├── HttpResponseTest.java
│ │ │ │ └── OkHttpHttpClientTest.java
│ │ │ └── socket/
│ │ │ ├── DefaultTsunamiSocketFactoryTest.java
│ │ │ ├── TsunamiSocketFactoryCliOptionsTest.java
│ │ │ └── TsunamiSocketFactoryModuleTest.java
│ │ ├── server/
│ │ │ └── CompactRunRequestHelperTest.java
│ │ ├── time/
│ │ │ ├── SystemUtcClockModuleTest.java
│ │ │ └── testing/
│ │ │ ├── FakeUtcClockModuleTest.java
│ │ │ └── FakeUtcClockTest.java
│ │ └── version/
│ │ ├── ComparisonUtilityTest.java
│ │ ├── EqualsTestCase.java
│ │ ├── KnownQualifierTest.java
│ │ ├── LessThanTestCase.java
│ │ ├── SegmentTest.java
│ │ ├── TokenTest.java
│ │ ├── VersionRangeTest.java
│ │ ├── VersionSetTest.java
│ │ └── VersionTest.java
│ └── resources/
│ └── com/
│ └── google/
│ └── tsunami/
│ └── common/
│ └── net/
│ └── http/
│ └── testdata/
│ ├── README.md
│ └── tsunami_test_server.p12
├── core.Dockerfile
├── devel.Dockerfile
├── docs/
│ ├── _config.yml
│ ├── _data/
│ │ └── nav.yml
│ ├── _includes/
│ │ └── nav.html
│ ├── _layouts/
│ │ ├── default.html
│ │ ├── home.html
│ │ └── post.html
│ ├── _posts/
│ │ ├── 2024-03-19-tsunami-network-scanner-ai-security.md
│ │ ├── 2025-06-18-changes-to-tsunami.md
│ │ └── 2025-10-16-october-update-tsunami-prp.md
│ ├── about/
│ │ └── index.md
│ ├── assets/
│ │ └── css/
│ │ └── style.scss
│ ├── blog/
│ │ └── index.html
│ ├── contribute/
│ │ ├── code-of-conduct.md
│ │ ├── contributing.md
│ │ └── index.md
│ ├── howto/
│ │ ├── common-patterns.md
│ │ ├── howto.md
│ │ ├── index.md
│ │ ├── new-detector/
│ │ │ ├── new-detector-java.md
│ │ │ └── templated/
│ │ │ ├── 00-getting-started.md
│ │ │ ├── 01-introduction.md
│ │ │ ├── 02-bootstrapping.md
│ │ │ ├── 03-first-actions.md
│ │ │ ├── 04-workflows.md
│ │ │ ├── 05-variables.md
│ │ │ ├── 06-callback-server.md
│ │ │ ├── 07-cleanup-actions.md
│ │ │ ├── 08-writing-unit-tests.md
│ │ │ ├── appendix-naming-actions.md
│ │ │ ├── appendix-naming-plugin.md
│ │ │ ├── appendix-naming-tests.md
│ │ │ ├── appendix-using-linter.md
│ │ │ ├── glossary-predefined-variables.md
│ │ │ └── glossary-tests-magic-uri.md
│ │ └── orchestration.md
│ └── index.md
├── full.Dockerfile
├── go.mod
├── main/
│ ├── README.md
│ ├── build.gradle
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── com/
│ │ └── google/
│ │ └── tsunami/
│ │ └── main/
│ │ └── cli/
│ │ ├── LanguageServerOptions.java
│ │ ├── ScanResultsArchiver.java
│ │ ├── ScanResultsArchiverModule.java
│ │ ├── TsunamiCli.java
│ │ ├── option/
│ │ │ ├── MainCliOptions.java
│ │ │ ├── OutputDataFormat.java
│ │ │ └── validator/
│ │ │ ├── IpV4Validator.java
│ │ │ ├── IpV6Validator.java
│ │ │ └── IpValidator.java
│ │ └── server/
│ │ ├── RemoteServerLoader.java
│ │ └── RemoteServerLoaderModule.java
│ └── test/
│ └── java/
│ └── com/
│ └── google/
│ └── tsunami/
│ └── main/
│ └── cli/
│ ├── LanguageServerOptionsTest.java
│ ├── ScanResultsArchiverTest.java
│ ├── TsunamiCliTest.java
│ ├── option/
│ │ ├── MainCliOptionsTest.java
│ │ ├── OutputDataFormatTest.java
│ │ └── validator/
│ │ ├── IpV4ValidatorTest.java
│ │ ├── IpV6ValidatorTest.java
│ │ └── IpValidatorTest.java
│ └── server/
│ └── RemoteServerLoaderTest.java
├── plugin/
│ ├── README.md
│ ├── build.gradle
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── tsunami/
│ │ │ └── plugin/
│ │ │ ├── LanguageServerException.java
│ │ │ ├── PluginBootstrapModule.java
│ │ │ ├── PluginDefinition.java
│ │ │ ├── PluginExecutionException.java
│ │ │ ├── PluginExecutionModule.java
│ │ │ ├── PluginExecutionResult.java
│ │ │ ├── PluginExecutionThreadPool.java
│ │ │ ├── PluginExecutor.java
│ │ │ ├── PluginExecutorImpl.java
│ │ │ ├── PluginExecutorModule.java
│ │ │ ├── PluginLoadingModule.java
│ │ │ ├── PluginManager.java
│ │ │ ├── PluginManagerCliOptions.java
│ │ │ ├── PluginServiceClient.java
│ │ │ ├── PluginType.java
│ │ │ ├── PortScanner.java
│ │ │ ├── RemoteVulnDetector.java
│ │ │ ├── RemoteVulnDetectorImpl.java
│ │ │ ├── RemoteVulnDetectorLoadingModule.java
│ │ │ ├── ServiceFingerprinter.java
│ │ │ ├── TcsClient.java
│ │ │ ├── TcsClientCliOptions.java
│ │ │ ├── TcsConfigProperties.java
│ │ │ ├── TsunamiPlugin.java
│ │ │ ├── VulnDetector.java
│ │ │ ├── annotations/
│ │ │ │ ├── ForOperatingSystemClass.java
│ │ │ │ ├── ForServiceName.java
│ │ │ │ ├── ForSoftware.java
│ │ │ │ ├── ForWebService.java
│ │ │ │ ├── PluginInfo.java
│ │ │ │ └── RequiresCallbackServer.java
│ │ │ ├── payload/
│ │ │ │ ├── NotImplementedException.java
│ │ │ │ ├── Payload.java
│ │ │ │ ├── PayloadGenerator.java
│ │ │ │ ├── PayloadGeneratorModule.java
│ │ │ │ ├── PayloadSecretGenerator.java
│ │ │ │ ├── README.md
│ │ │ │ ├── Validator.java
│ │ │ │ └── testing/
│ │ │ │ ├── FakePayloadGeneratorModule.java
│ │ │ │ └── PayloadTestHelper.java
│ │ │ └── testing/
│ │ │ ├── FailedPortScanner.java
│ │ │ ├── FailedPortScannerBootstrapModule.java
│ │ │ ├── FailedRemoteVulnDetector.java
│ │ │ ├── FailedRemoteVulnDetectorBootstrapModule.java
│ │ │ ├── FailedServiceFingerprinter.java
│ │ │ ├── FailedServiceFingerprinterBootstrapModule.java
│ │ │ ├── FailedVulnDetector.java
│ │ │ ├── FailedVulnDetectorBootstrapModule.java
│ │ │ ├── FakePluginExecutionModule.java
│ │ │ ├── FakePortScanner.java
│ │ │ ├── FakePortScanner2.java
│ │ │ ├── FakePortScannerBootstrapModule.java
│ │ │ ├── FakePortScannerBootstrapModule2.java
│ │ │ ├── FakePortScannerBootstrapModuleEmpty.java
│ │ │ ├── FakePortScannerEmpty.java
│ │ │ ├── FakeRemoteVulnDetector.java
│ │ │ ├── FakeRemoteVulnDetectorBootstrapModule.java
│ │ │ ├── FakeServiceFingerprinter.java
│ │ │ ├── FakeServiceFingerprinterBootstrapModule.java
│ │ │ ├── FakeVulnDetector.java
│ │ │ ├── FakeVulnDetector2.java
│ │ │ ├── FakeVulnDetectorBootstrapModule.java
│ │ │ ├── FakeVulnDetectorBootstrapModule2.java
│ │ │ ├── FakeVulnDetectorBootstrapModuleEmpty.java
│ │ │ └── FakeVulnDetectorEmpty.java
│ │ └── resources/
│ │ └── com/
│ │ └── google/
│ │ └── tsunami/
│ │ └── plugin/
│ │ └── payload/
│ │ └── payload_definitions.yaml
│ └── test/
│ └── java/
│ └── com/
│ └── google/
│ └── tsunami/
│ └── plugin/
│ ├── PluginDefinitionTest.java
│ ├── PluginExecutorImplTest.java
│ ├── PluginLoadingModuleTest.java
│ ├── PluginManagerTest.java
│ ├── PluginServiceClientTest.java
│ ├── RemoteVulnDetectorImplTest.java
│ ├── RemoteVulnDetectorLoadingModuleTest.java
│ ├── TcsClientTest.java
│ └── payload/
│ ├── PayloadGeneratorModuleTest.java
│ ├── PayloadGeneratorWithCallbackServerTest.java
│ ├── PayloadGeneratorWithoutCallbackServerTest.java
│ ├── PayloadSecretGeneratorTest.java
│ └── PayloadTest.java
├── plugin_server/
│ └── py/
│ ├── common/
│ │ ├── data/
│ │ │ ├── network_endpoint_utils.py
│ │ │ ├── network_endpoint_utils_test.py
│ │ │ ├── network_service_utils.py
│ │ │ └── network_service_utils_test.py
│ │ └── net/
│ │ └── http/
│ │ ├── host_resolver_http_adapter.py
│ │ ├── host_resolver_http_adapter_test.py
│ │ ├── http_client.py
│ │ ├── http_header_fields.py
│ │ ├── http_header_fields_test.py
│ │ ├── http_headers.py
│ │ ├── http_headers_test.py
│ │ ├── http_method.py
│ │ ├── http_request.py
│ │ ├── http_request_test.py
│ │ ├── http_response.py
│ │ ├── http_response_test.py
│ │ ├── http_status.py
│ │ ├── http_status_test.py
│ │ ├── requests_http_client.py
│ │ └── requests_http_client_test.py
│ ├── plugin/
│ │ ├── payload/
│ │ │ ├── payload.py
│ │ │ ├── payload_generator.py
│ │ │ ├── payload_generator_test.py
│ │ │ ├── payload_generator_test_helper.py
│ │ │ ├── payload_secret_generator.py
│ │ │ ├── payload_secret_generator_test.py
│ │ │ ├── payload_test.py
│ │ │ ├── payload_utility.py
│ │ │ ├── payload_utility_test.py
│ │ │ └── validator.py
│ │ ├── tcs_client.py
│ │ └── tcs_client_test.py
│ ├── plugin_server.py
│ ├── plugin_service.py
│ ├── plugin_service_test.py
│ ├── requirements.in
│ ├── requirements.txt
│ └── tsunami_plugin.py
├── proto/
│ ├── build.gradle
│ ├── detection.proto
│ ├── go/
│ │ ├── detection_go_proto/
│ │ │ └── detection.pb.go
│ │ ├── network_go_proto/
│ │ │ └── network.pb.go
│ │ ├── network_service_go_proto/
│ │ │ └── network_service.pb.go
│ │ ├── payload_generator_go_proto/
│ │ │ └── payload_generator.pb.go
│ │ ├── plugin_representation_go_proto/
│ │ │ └── plugin_representation.pb.go
│ │ ├── plugin_service_go_proto/
│ │ │ └── plugin_service.pb.go
│ │ ├── reconnaissance_go_proto/
│ │ │ └── reconnaissance.pb.go
│ │ ├── scan_results_go_proto/
│ │ │ └── scan_results.pb.go
│ │ ├── scan_target_go_proto/
│ │ │ └── scan_target.pb.go
│ │ ├── software_go_proto/
│ │ │ └── software.pb.go
│ │ ├── vulnerability_go_proto/
│ │ │ └── vulnerability.pb.go
│ │ └── web_crawl_go_proto/
│ │ └── web_crawl.pb.go
│ ├── network.proto
│ ├── network_service.proto
│ ├── payload_generator.proto
│ ├── plugin_representation.proto
│ ├── plugin_service.proto
│ ├── reconnaissance.proto
│ ├── scan_results.proto
│ ├── scan_target.proto
│ ├── software.proto
│ ├── tsunami_go_proto/
│ │ ├── detection.pb.go
│ │ ├── network.pb.go
│ │ ├── network_service.pb.go
│ │ ├── payload_generator.pb.go
│ │ ├── plugin_representation.pb.go
│ │ ├── plugin_service.pb.go
│ │ ├── reconnaissance.pb.go
│ │ ├── scan_results.pb.go
│ │ ├── scan_target.pb.go
│ │ ├── software.pb.go
│ │ ├── vulnerability.pb.go
│ │ └── web_crawl.pb.go
│ ├── vulnerability.proto
│ └── web_crawl.proto
├── settings.gradle
├── tsunami.yaml
├── tsunami_tcs.yaml
└── workflow/
├── README.md
├── build.gradle
└── src/
├── main/
│ └── java/
│ └── com/
│ └── google/
│ └── tsunami/
│ └── workflow/
│ ├── AdvisoriesWorkflow.java
│ ├── DefaultScanningWorkflow.java
│ ├── ExecutionStage.java
│ ├── ExecutionTracer.java
│ └── ScanningWorkflowException.java
└── test/
└── java/
└── com/
└── google/
└── tsunami/
└── workflow/
├── DefaultScanningWorkflowTest.java
└── ExecutionTracerTest.java
================================================
FILE CONTENTS
================================================
================================================
FILE: .dockerignore
================================================
# Git-related files
.gitattributes
.gitignore
.git/
# IDE files
.idea/
.vscode/
# Build cache
.gradle/
# Documentation
docs/
LICENSE
README.md
# Miscellaneous
quick_start.sh
Dockerfile
.dockerignore
================================================
FILE: .gitattributes
================================================
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf
================================================
FILE: .github/workflows/core-build.yml
================================================
name: core-build
on:
pull_request:
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: google/tsunami-scanner-core
jobs:
build-image:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build Docker image
id: build
uses: docker/build-push-action@v6
with:
context: .
file: core.Dockerfile
push: false
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
labels: ${{ steps.meta.outputs.labels }}
================================================
FILE: .github/workflows/core-push.yml
================================================
name: core-push
on:
push:
branches:
- master
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: google/tsunami-scanner-core
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
with:
context: .
file: core.Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
labels: ${{ steps.meta.outputs.labels }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
================================================
FILE: .github/workflows/devel-push.yml
================================================
name: devel-push
on:
schedule:
- cron: "0 */4 * * *"
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: google/tsunami-scanner-devel
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
with:
context: .
file: devel.Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
labels: ${{ steps.meta.outputs.labels }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
================================================
FILE: .github/workflows/full-push.yml
================================================
name: full-push
on:
schedule:
- cron: "0 */4 * * *"
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: google/tsunami-scanner-full
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
with:
context: .
push: true
file: full.Dockerfile
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
labels: ${{ steps.meta.outputs.labels }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
================================================
FILE: .gitignore
================================================
# Gradle
build
gradle.properties
.gradle
local.properties
out
# IntelliJ IDEA
.idea
*.iml
*.ipr
*.iws
classes
# Eclipse
.classpath
.factorypath
.project
.settings
bin
eclipsebin
# OS X
.DS_Store
# Emacs
*~
\#*\#
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
# Tsunami

Tsunami is a general purpose network security scanner with an extensible plugin
system for detecting high severity vulnerabilities with high confidence.
To learn more about Tsunami, visit our
[documentation](https://google.github.io/tsunami-security-scanner/).
Tsunami relies heavily on its plugin system to provide basic scanning
capabilities. All publicly available Tsunami plugins are hosted in a separate
[google/tsunami-security-scanner-plugins](https://github.com/google/tsunami-security-scanner-plugins)
repository.
## Quick start
Please see the documentation on how to
[build and run Tsunami](https://google.github.io/tsunami-security-scanner/howto/howto)
## Contributing
Read how to
[contribute to Tsunami](https://google.github.io/tsunami-security-scanner/contribute/).
## License
Tsunami is released under the [Apache 2.0 license](LICENSE).
```
Copyright 2025 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
## Disclaimers
Tsunami is not an official Google product.
================================================
FILE: build.gradle
================================================
// Current gradle version 6.5.
plugins {
id 'net.ltgt.errorprone' apply false version "4.2.0"
id "com.gradleup.shadow" version "8.3.6"
}
subprojects {
apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: 'idea'
apply plugin: 'net.ltgt.errorprone'
apply plugin: 'com.gradleup.shadow'
group = 'com.google.tsunami'
version = '0.1.1-SNAPSHOT' // Current Tsunami version
repositories {
maven { // The google mirror is less flaky than mavenCentral()
url 'https://maven-central.storage-download.googleapis.com/repos/central/data/'
}
mavenCentral()
mavenLocal()
}
if (rootProject.properties.get('errorProne', true)) {
dependencies {
errorprone "com.google.errorprone:error_prone_core:2.38.0"
errorproneJavac 'com.google.errorprone:javac:9+181-r4173-1'
}
// Disable ErrorProne for all generated codes.
tasks.withType(JavaCompile).configureEach {
options.errorprone.disableWarningsInGeneratedCode = false
options.errorprone.excludedPaths = '.*/build/generated/.*'
}
} else {
// Disable Error Prone
allprojects {
afterEvaluate { project ->
project.tasks.withType(JavaCompile) {
options.errorprone.enabled = false
}
}
}
}
plugins.withId('java') {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
java.withJavadocJar()
java.withSourcesJar()
jar.manifest {
attributes('Implementation-Title': name,
'Implementation-Version': version,
'Built-By': System.getProperty('user.name'),
'Built-JDK': System.getProperty('java.version'),
'Source-Compatibility': sourceCompatibility,
'Target-Compatibility': targetCompatibility)
}
// Log stacktrace to console when test fails.
test {
testLogging {
exceptionFormat = 'full'
showExceptions true
showCauses true
showStackTraces true
}
maxHeapSize = '1500m'
}
}
plugins.withId('maven-publish') {
shadowJar {
archiveClassifier = null
}
}
}
================================================
FILE: common/README.md
================================================
# Tsunami Common Libraries
## Overview
This module provides a set of common libraries and utilities for Tsunami
Security Scanner.
================================================
FILE: common/build.gradle
================================================
description = 'Tsunami: Common'
dependencies {
implementation project(':tsunami-proto')
implementation "com.beust:jcommander:1.48"
implementation "com.google.auto.value:auto-value-annotations:1.11.0"
implementation "com.google.cloud:google-cloud-storage:1.103.1"
implementation "com.google.code.gson:gson:2.10.1"
implementation "com.google.flogger:flogger-system-backend:0.9"
implementation "com.google.flogger:flogger:0.9"
implementation "com.google.flogger:google-extensions:0.9"
implementation "com.google.guava:guava:33.0.0-jre"
implementation "com.google.inject:guice:6.0.0"
implementation "com.google.inject.extensions:guice-assistedinject:6.0.0"
implementation "com.google.truth:truth:1.4.4"
implementation "com.squareup.okhttp3:okhttp:3.12.0"
implementation "io.github.classgraph:classgraph:4.8.65"
implementation "org.yaml:snakeyaml:1.26"
runtimeOnly "com.mysql:mysql-connector-j:8.0.33"
runtimeOnly "org.apache.hive:hive-jdbc:4.0.1"
runtimeOnly "org.postgresql:postgresql:42.6.0"
annotationProcessor "com.google.auto.value:auto-value:1.10.4"
testAnnotationProcessor "com.google.auto.value:auto-value:1.10.4"
testImplementation "com.google.guava:guava-testlib:33.0.0-jre"
testImplementation "com.google.truth:truth:1.4.4"
testImplementation "com.google.truth.extensions:truth-java8-extension:1.4.4"
testImplementation "com.google.truth.extensions:truth-proto-extension:1.4.4"
testImplementation "com.squareup.okhttp3:mockwebserver:3.12.0"
testImplementation "junit:junit:4.13.2"
testImplementation "org.mockito:mockito-core:5.18.0"
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/ErrorCode.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common;
/** Error codes for Tsunami scanner executions. */
public enum ErrorCode {
CONFIG_ERROR,
PLUGIN_EXECUTION_ERROR,
WORKFLOW_ERROR,
LANGUAGE_SERVER_ERROR,
UNKNOWN;
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/TsunamiException.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Strings;
/** Base exception definition of all Tsunami execution errors. */
public class TsunamiException extends RuntimeException {
private final ErrorCode errorCode;
public TsunamiException() {
this(ErrorCode.UNKNOWN);
}
public TsunamiException(ErrorCode errorCode) {
this(errorCode, null);
}
public TsunamiException(ErrorCode errorCode, String message) {
this(errorCode, message, null);
}
public TsunamiException(ErrorCode errorCode, String message, Throwable cause) {
super(buildExceptionMessage(checkNotNull(errorCode), message), cause);
this.errorCode = errorCode;
}
private static String buildExceptionMessage(ErrorCode errorCode, String message) {
StringBuilder exceptionMessageBuilder = new StringBuilder();
exceptionMessageBuilder.append("(Tsunami error ").append(errorCode).append(")");
if (!Strings.isNullOrEmpty(message)) {
exceptionMessageBuilder.append(": ").append(message);
}
return exceptionMessageBuilder.toString();
}
public ErrorCode getErrorCode() {
return errorCode;
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/cli/CliOption.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.cli;
/**
* A marker interface for a subset of command line options used in Tsunami modules.
*
* <p>Client should ALWAYS mark its options with this interface so that they can be identified by
* {@link io.github.classgraph.ClassGraph}. All implementations of {@link CliOption} should provide
* a no argument constructor or omit constructors completely.
*/
public interface CliOption {
/**
* Performs additional validation logic across options defined in the same {@link CliOption}.
*
* <p>If validation failed, simply throw a {@link com.beust.jcommander.ParameterException}.
*/
void validate();
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/cli/CliOptionsModule.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.cli;
import static com.google.common.base.Preconditions.checkNotNull;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterException;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.GoogleLogger;
import com.google.inject.AbstractModule;
import io.github.classgraph.ClassInfo;
import io.github.classgraph.ScanResult;
import java.lang.reflect.Constructor;
/**
* A Guice module that parses CLI arguments for all {@link CliOption} implementations at runtime.
*
* <p>This module relies on the {@link io.github.classgraph.ClassGraph} scan results to identify all
* {@link CliOption} implementations at runtime. Each implementation is bound to a singleton object
* of that impl and registered to JCommander for CLI parsing.
*/
public final class CliOptionsModule extends AbstractModule {
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
private static final String CLI_OPTION_INTERFACE = "com.google.tsunami.common.cli.CliOption";
private final ScanResult scanResult;
private final String[] args;
private final JCommander jCommander;
public CliOptionsModule(ScanResult scanResult, String programName, String[] args) {
this.scanResult = checkNotNull(scanResult);
this.args = checkNotNull(args);
this.jCommander = new JCommander();
jCommander.setProgramName(programName);
}
@Override
protected void configure() {
// For each CliOption installed at runtime, bind a singleton instance and register the instance
// to JCommander for parsing.
ImmutableList.Builder<CliOption> cliOptions = ImmutableList.builder();
for (ClassInfo classInfo :
scanResult
.getClassesImplementing(CLI_OPTION_INTERFACE)
.filter(classInfo -> !classInfo.isInterface())) {
logger.atInfo().log("Found CliOption: %s", classInfo.getName());
CliOption cliOption = bindCliOption(classInfo.loadClass(CliOption.class));
jCommander.addObject(cliOption);
cliOptions.add(cliOption);
}
// Parse command arguments or die.
try {
jCommander.parse(args);
cliOptions.build().forEach(CliOption::validate);
} catch (ParameterException e) {
jCommander.usage();
throw e;
}
}
private <T> T bindCliOption(Class<T> cliOptionClass) {
try {
Constructor<T> cliOptionCtor = cliOptionClass.getDeclaredConstructor();
// Always create an instance of the CliOption regardless of scope.
cliOptionCtor.setAccessible(true);
T cliOption = cliOptionCtor.newInstance();
bind(cliOptionClass).toInstance(cliOption);
return cliOption;
} catch (ReflectiveOperationException e) {
throw new AssertionError(
String.format(
"CliOption '%s' must be constructable via a no-argument constructor",
cliOptionClass.getTypeName()),
e);
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/command/CommandExecutionThreadPool.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.command;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Qualifier;
/** Annotates the thread pool to use for executing native commands. */
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandExecutionThreadPool {}
================================================
FILE: common/src/main/java/com/google/tsunami/common/command/CommandExecutor.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.command;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.flogger.GoogleLogger;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import javax.annotation.Nullable;
/** Helper class that handles running a command line and collecting output and errors. */
// TODO(b/145315535): reimplement this class so that it is:
// 1. guice injectable in order to hide Executor interface.
// 2. unit testable to prevent actually executing commands in test.
public class CommandExecutor {
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
private static final Joiner COMMAND_ARGS_JOINER = Joiner.on(" ");
private final ProcessBuilder processBuilder;
private final String[] args;
private Process process;
@Nullable private String output;
@Nullable private String error;
public CommandExecutor(String... args) {
this.args = checkNotNull(args);
this.processBuilder = new ProcessBuilder(args);
}
/*
* Executes the command and uses a {@link ThreadPoolExecutor} to collect output and error.
*
* This is a convenience method for testing purposes only as the executor is not shared and
* therefore defeats the purpose of having a cached thread pool.
*/
@VisibleForTesting
Process execute() throws IOException, InterruptedException, ExecutionException {
// Nmap is a long running process and the collectStream method is a blocking method.
// By default CompletableFuture uses ForkJoinPool, which is for suitable short
// non-blocking operations.
Executor executor = Executors.newCachedThreadPool();
return execute(executor);
}
/**
* Starts the command and uses the passed executor to collect output and error streams.
*
* <p>IMPORTANT: The stream collection uses an IO blocking method and the passed executor must be
* well suited for the task. {@link ThreadPoolExecutor} is a viable option.
*
* @param executor The executor to collect output and error streams.
* @return Started {@link Process} object.
* @throws IOException if an I/O error occurs when starting the command executing process.
* @throws InterruptedException if interrupted while waiting for the command's output.
* @throws ExecutionException if the command execution failed.
*/
public Process execute(Executor executor)
throws IOException, InterruptedException, ExecutionException {
logger.atInfo().log("Executing the following command: '%s'", COMMAND_ARGS_JOINER.join(args));
process = processBuilder.start();
output =
CompletableFuture.supplyAsync(() -> collectStream(process.getInputStream()), executor)
.get();
error =
CompletableFuture.supplyAsync(() -> collectStream(process.getErrorStream()), executor)
.get();
return process;
}
/**
* Starts the command and asynchronously collect output and error.
*
* @return Started {@link Process} object.
* @throws IOException if an I/O error occurs when starting the command executing process.
* @throws InterruptedException if interrupted while waiting for the command's output.
* @throws ExecutionException if the command execution failed.
*/
public Process executeAsync() throws IOException, InterruptedException, ExecutionException {
logger.atInfo().log("Executing the following command: '%s'", COMMAND_ARGS_JOINER.join(args));
process = processBuilder.inheritIO().start();
return process;
}
/**
* Starts the command without collecting output and error streams.
*
* @return Started {@link Process} object.
* @throws IOException if an I/O error occurs when starting the command executing process.
* @throws InterruptedException if interrupted while starting the command executing process.
* @throws ExecutionException if the command execution failed.
*/
public Process executeWithNoStreamCollection()
throws IOException, InterruptedException, ExecutionException {
logger.atInfo().log("Executing the following command: '%s'", COMMAND_ARGS_JOINER.join(args));
process = processBuilder.start();
return process;
}
@Nullable
public String getOutput() {
return output;
}
@Nullable
public String getError() {
return error;
}
private static String collectStream(InputStream stream) {
StringBuilder stringBuilder = new StringBuilder();
try {
String output;
BufferedReader streamReader = new BufferedReader(new InputStreamReader(stream, UTF_8));
while ((output = streamReader.readLine()) != null) {
stringBuilder.append(output);
stringBuilder.append("\n");
}
} catch (IOException e) {
logger.atWarning().withCause(e).log("Error collecting output stream from command execution.");
}
return stringBuilder.toString();
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/command/CommandExecutorFactory.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.command;
/** Utility class to simplify the creation and testing of {@link CommandExecutor} instances. */
public class CommandExecutorFactory {
private static CommandExecutor instance;
/**
* Sets an executor instance that will be returned by all future calls to {@link
* CommandExecutorFactory#create(String...)}
*
* @param executor The {@link CommandExecutor} returned by this factory.
*/
public static void setInstance(CommandExecutor executor) {
instance = executor;
}
/**
* Creates a new {@link CommandExecutor} if none is set.
*
* @param args List of arguments to pass to the newly created {@link CommandExecutor}.
* @return the {@link CommandExecutor} instance created by this factory.
*/
public static CommandExecutor create(String... args) {
if (instance == null) {
return new CommandExecutor(args);
}
return instance;
}
private CommandExecutorFactory() {}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/command/CommandExecutorModule.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.command;
import com.google.inject.AbstractModule;
import com.google.tsunami.common.concurrent.ThreadPoolModule;
/** Installs dependencies used by {@link CommandExecutor}. */
public class CommandExecutorModule extends AbstractModule {
@Override
protected void configure() {
install(
new ThreadPoolModule.Builder()
.setName("CommandExecutor")
.setCoreSize(4)
.setMaxSize(8)
.setQueueCapacity(32)
.setDaemon(true)
.setPriority(Thread.NORM_PRIORITY)
.setAnnotation(CommandExecutionThreadPool.class)
.build());
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/concurrent/BaseThreadPoolModule.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.concurrent;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.base.Strings;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.inject.AbstractModule;
import com.google.inject.Key;
import java.lang.annotation.Annotation;
import java.time.Duration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
import java.util.concurrent.TimeUnit;
import javax.inject.Provider;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* The base module for binding a thread pool.
*
* <p>This module is essentially a thin wrapper around {@link ThreadFactoryBuilder} and the
* corresponding {@link ExecutorService} families. Based on the intended usage, it is expected that
* subclasses of this module should provides bindings to a concrete thread pool implementation of
* {@link ExecutorService}. This base module wraps the actual {@link ExecutorService} implementation
* in order to support {@link com.google.common.util.concurrent.ListenableFuture} usage in the code
* base.
*
* @param <ExecutorServiceT> The expected thread pool implementation, must be a subclass of {@link
* ListeningExecutorService}.
*/
abstract class BaseThreadPoolModule<ExecutorServiceT extends ListeningExecutorService>
extends AbstractModule {
private final ThreadFactory factory;
private final int maxSize;
private final int coreSize;
private final long keepAliveSeconds;
private final @Nullable Duration shutdownDelay;
private final Key<ExecutorServiceT> key;
private final Class<ExecutorServiceT> executorServiceTypeClass;
private final RejectedExecutionHandler rejectedExecutionHandler;
BaseThreadPoolModule(BaseThreadPoolModuleBuilder<ExecutorServiceT, ?> builder) {
checkNotNull(builder);
this.factory = builder.factoryBuilder.build();
this.maxSize = builder.maxSize;
this.coreSize = builder.coreSize;
this.keepAliveSeconds = builder.keepAliveSeconds;
this.shutdownDelay = builder.daemon ? builder.shutdownDelay : null;
this.key = builder.key;
this.executorServiceTypeClass = builder.executorServiceTypeClass;
this.rejectedExecutionHandler = builder.rejectedExecutionHandler;
}
@Override
protected final void configure() {
configureThreadPool(key);
}
/** Subclasses should override this method for providing Guice bindings. */
abstract void configureThreadPool(Key<ExecutorServiceT> key);
/** Base {@link Provider} implementation for providing the target thread pool. */
abstract class BaseThreadPoolProvider implements Provider<ExecutorServiceT> {
abstract ExecutorService createThreadPool(
int coreSize,
int maxSize,
long keepAliveSeconds,
ThreadFactory factory,
RejectedExecutionHandler rejectedExecutionHandler);
@Override
public final ExecutorServiceT get() {
ExecutorService service =
createThreadPool(coreSize, maxSize, keepAliveSeconds, factory, rejectedExecutionHandler);
if (shutdownDelay != null) {
MoreExecutors.addDelayedShutdownHook(
service, shutdownDelay.toMillis(), TimeUnit.MILLISECONDS);
}
return executorServiceTypeClass.cast(MoreExecutors.listeningDecorator(service));
}
}
/** Base Builder for {@link BaseThreadPoolModule}. */
abstract static class BaseThreadPoolModuleBuilder<
ExecutorServiceT extends ListeningExecutorService,
BuilderImplT extends BaseThreadPoolModuleBuilder<ExecutorServiceT, BuilderImplT>> {
protected final ThreadFactoryBuilder factoryBuilder = new ThreadFactoryBuilder();
protected String name;
protected int maxSize;
protected int coreSize;
protected long keepAliveSeconds = 60L;
protected boolean daemon;
protected Duration shutdownDelay;
protected Key<ExecutorServiceT> key;
protected final Class<ExecutorServiceT> executorServiceTypeClass;
protected RejectedExecutionHandler rejectedExecutionHandler = new AbortPolicy();
BaseThreadPoolModuleBuilder(Class<ExecutorServiceT> executorServiceTypeClass) {
this.executorServiceTypeClass = checkNotNull(executorServiceTypeClass);
}
abstract BuilderImplT self();
/**
* Sets the name used to name the threads; automatically suffixed with "-%s"to incorporate the
* thread number
*
* @param name the name of the thread pool.
* @return the Builder instance itself.
*/
public BuilderImplT setName(String name) {
checkArgument(!Strings.isNullOrEmpty(name), "Name should not be empty");
this.name = name;
return self();
}
/**
* Sets the maximum number of threads allowed in the pool; value should be positive.
*
* @param maxSize the maximum number of threads allowed in this thread pool.
* @return the Builder instance itself.
*/
BuilderImplT setMaxSize(int maxSize) {
checkArgument(maxSize > 0, "Max thread pool size should be positive.");
this.maxSize = maxSize;
return self();
}
/**
* Sets the number of threads to keep in the pool.
*
* @param coreSize the minimum number of threads to keep alive in this thread pool.
* @return the Builder instance itself.
*/
BuilderImplT setCoreSize(int coreSize) {
checkArgument(coreSize >= 0, "The core pool size should be non-negative.");
this.coreSize = coreSize;
return self();
}
/**
* Sets the keep alive time in seconds for the threads not in core pool.
*
* @param keepAliveSeconds the maximum number of seconds an idle thread in this pool can keep
* alive before being terminated.
* @return the Builder instance itself.
*/
public BuilderImplT setKeepAliveSeconds(long keepAliveSeconds) {
checkArgument(keepAliveSeconds >= 0, "The keep alive time should be non-negative.");
this.keepAliveSeconds = keepAliveSeconds;
return self();
}
/**
* Sets whether or not new threads created by the pool will be daemon threads.*
*
* @param daemon whether threads created in this pool are daemon threads.
* @return the Builder instance itself.
*/
public BuilderImplT setDaemon(boolean daemon) {
factoryBuilder.setDaemon(daemon);
this.daemon = daemon;
return self();
}
/**
* Sets how long the JVM should wait to exit for daemon threads to complete.
*
* <p>This has no effect if the pool does not use daemon threads.
*
* @param shutdownDelay the delay enforced during the thread pool shutdown.
* @return the Builder instance itself.
*/
public BuilderImplT setDelayedShutdown(Duration shutdownDelay) {
this.shutdownDelay = checkNotNull(shutdownDelay);
return self();
}
/**
* Sets the priority for threads created by the pool.
*
* @param priority the priority of the threads created by this pool.
* @return the Builder instance itself.
*/
public BuilderImplT setPriority(int priority) {
factoryBuilder.setPriority(priority);
return self();
}
/**
* Sets the binding annotation.
*
* @param annotation the Guice binding annotation for this thread pool.
* @return the Builder instance itself.
*/
public BuilderImplT setAnnotation(Annotation annotation) {
key = Key.get(executorServiceTypeClass, checkNotNull(annotation));
return self();
}
/**
* Sets the binding annotation.
*
* @param annotationClass the Guice binding annotation class for this thread pool.
* @return the Builder instance itself.
*/
public BuilderImplT setAnnotation(Class<? extends Annotation> annotationClass) {
key = Key.get(executorServiceTypeClass, checkNotNull(annotationClass));
return self();
}
/**
* Sets the handler to use when thread execution is blocked due to thread bounds and queue
* capacities are reached.
*
* <p>By default, {@link AbortPolicy} is used for rejected execution, which throws the {@link
* java.util.concurrent.RejectedExecutionException}.
*
* @param rejectedExecutionHandler A handler for tasks that cannot be executed by this thread
* pool.
* @return the Builder instance itself.
*/
public BuilderImplT setRejectedExecutionHandler(
RejectedExecutionHandler rejectedExecutionHandler) {
this.rejectedExecutionHandler = checkNotNull(rejectedExecutionHandler);
return self();
}
final void validateAll() {
checkState(!Strings.isNullOrEmpty(name), "Name is required.");
checkState(
maxSize > 0,
"Max thread pool size must be positive. Did you forget setting maximum thread pool size"
+ " by calling setMaxSize?");
checkState(
coreSize <= maxSize, "Thread pool core size should be less than or equal to max size.");
checkState(key != null, "Annotation is required.");
validate();
}
abstract void validate();
public final AbstractModule build() {
validateAll();
return newModule();
}
abstract AbstractModule newModule();
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/concurrent/ScheduledThreadPoolModule.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.concurrent;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.inject.Key;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import javax.inject.Singleton;
/**
* A helper module for binding a scheduled thread pool. The module will bind a {@link
* ScheduledExecutorService} and a {@link ListeningScheduledExecutorService} to a singleton thread
* pool that is annotated with the annotation passed to the builder.
*/
public final class ScheduledThreadPoolModule
extends BaseThreadPoolModule<ListeningScheduledExecutorService> {
ScheduledThreadPoolModule(Builder builder) {
super(builder);
}
@Override
void configureThreadPool(Key<ListeningScheduledExecutorService> key) {
bind(key.ofType(ScheduledExecutorService.class)).to(key);
bind(key).toProvider(new ScheduledThreadPoolProvider()).in(Singleton.class);
}
private final class ScheduledThreadPoolProvider extends BaseThreadPoolProvider {
@Override
ScheduledThreadPoolExecutor createThreadPool(
int coreSize,
int maxSize,
long keepAliveSeconds,
ThreadFactory factory,
RejectedExecutionHandler rejectedExecutionHandler) {
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
new ScheduledThreadPoolExecutor(coreSize, factory, rejectedExecutionHandler);
scheduledThreadPoolExecutor.setMaximumPoolSize(maxSize);
scheduledThreadPoolExecutor.setKeepAliveTime(keepAliveSeconds, SECONDS);
return scheduledThreadPoolExecutor;
}
}
/**
* Builder for {@link ScheduledThreadPoolModule}.
*
* <p>NOTE: Unlike {@link ThreadPoolModule}, {@link ScheduledThreadPoolExecutor} acts as a
* fixed-sized pool using {@code corePoolSize} threads and an unbounded queue. So this builder
* only allows users to set a fixed thread pool size.
*/
public static final class Builder
extends BaseThreadPoolModuleBuilder<ListeningScheduledExecutorService, Builder> {
public Builder() {
super(ListeningScheduledExecutorService.class);
}
@Override
Builder self() {
return this;
}
/**
* Sets the size of the thread pool.
*
* @param size the size of the thread pool.
* @return the {@link Builder} instance itself.
*/
public Builder setSize(int size) {
checkArgument(size > 0, "Thread pool size should be positive.");
setCoreSize(size);
setMaxSize(size);
return this;
}
@Override
void validate() {}
@Override
ScheduledThreadPoolModule newModule() {
return new ScheduledThreadPoolModule(this);
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/concurrent/ThreadPoolModule.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.concurrent;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Key;
import com.google.inject.Singleton;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A helper module for binding a thread pool. The module will bind an {@link Executor}, {@link
* ExecutorService} and {@link ListeningExecutorService} annotated with the annotation passed to the
* builder.
*/
public final class ThreadPoolModule extends BaseThreadPoolModule<ListeningExecutorService> {
private final BlockingQueue<Runnable> blockingQueue;
private ThreadPoolModule(Builder builder) {
super(checkNotNull(builder));
this.blockingQueue = builder.getBlockingQueue();
}
@Override
void configureThreadPool(Key<ListeningExecutorService> key) {
bind(key.ofType(Executor.class)).to(key);
bind(key.ofType(ExecutorService.class)).to(key);
bind(key).toProvider(new ThreadPoolProvider()).in(Singleton.class);
}
private final class ThreadPoolProvider extends BaseThreadPoolProvider {
@Override
ThreadPoolExecutor createThreadPool(
int coreSize,
int maxSize,
long keepAliveSeconds,
ThreadFactory factory,
RejectedExecutionHandler rejectedExecutionHandler) {
return new ThreadPoolExecutor(
coreSize,
maxSize,
keepAliveSeconds,
TimeUnit.SECONDS,
blockingQueue,
factory,
rejectedExecutionHandler);
}
}
/** Builder for {@link ThreadPoolModule}. */
public static final class Builder
extends BaseThreadPoolModuleBuilder<ListeningExecutorService, Builder> {
private int queueCapacity = Integer.MAX_VALUE;
private @Nullable BlockingQueue<Runnable> blockingQueue;
public Builder() {
super(ListeningExecutorService.class);
}
@Override
Builder self() {
return this;
}
/** {@inheritDoc} */
@Override
public Builder setMaxSize(int maxSize) {
return super.setMaxSize(maxSize);
}
/** {@inheritDoc} */
@Override
public Builder setCoreSize(int coreSize) {
return super.setCoreSize(coreSize);
}
/**
* Sets the queue capacity for the thread pool.
*
* <p>NOTE: Users should NOT specify both this value and the {@link BlockingQueue} via {@link
* #setBlockingQueue}.
*
* <p>By default, {@link SynchronousQueue} will be used when {@code queueCapacity} is set to
* zero. Otherwise a {@link LinkedBlockingQueue} will be used.
*
* @param queueCapacity the capacity of the task queue.
* @return the Builder instance itself.
*/
public Builder setQueueCapacity(int queueCapacity) {
checkArgument(queueCapacity >= 0, "The queue capacity should be non-negative value.");
this.queueCapacity = queueCapacity;
return this;
}
/**
* Sets the {@link BlockingQueue} to use for holding tasks before they are executed.
*
* <p>NOTE: Do NOT set both {@link BlockingQueue} and {@code queueCapacity}. Only use this
* method to override the default {@link BlockingQueue} choice. See comments of {@link
* #getBlockingQueue} for which {@link BlockingQueue} is used by default.
*
* @param blockingQueue a {@link BlockingQueue} used for holding tasks before executing.
* @return the Builder instance itself.
*/
public Builder setBlockingQueue(BlockingQueue<Runnable> blockingQueue) {
this.blockingQueue = checkNotNull(blockingQueue);
return this;
}
private BlockingQueue<Runnable> getBlockingQueue() {
if (blockingQueue == null) {
return queueCapacity == 0
? new SynchronousQueue<>()
: new LinkedBlockingQueue<>(queueCapacity);
}
return blockingQueue;
}
private boolean isBoundedQueue() {
return (blockingQueue == null ? queueCapacity : blockingQueue.remainingCapacity())
< Integer.MAX_VALUE;
}
@Override
void validate() {
checkState(
blockingQueue == null || queueCapacity == Integer.MAX_VALUE,
"Both custom BlockingQueue and queue capacity are specified.");
if (coreSize < maxSize) {
checkState(
isBoundedQueue(),
"Finite capacity queue should be set when the core pool size is less than max pool"
+ " size. ThreadPoolExecutor will only create new threads past core size when the"
+ " queue is full.");
}
}
@Override
ThreadPoolModule newModule() {
return new ThreadPoolModule(this);
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/config/ConfigException.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.config;
import com.google.tsunami.common.ErrorCode;
import com.google.tsunami.common.TsunamiException;
/** Exception when handling Tsunami configs. */
public class ConfigException extends TsunamiException {
public ConfigException(String message) {
super(ErrorCode.CONFIG_ERROR, message);
}
public ConfigException(String message, Throwable cause) {
super(ErrorCode.CONFIG_ERROR, message, cause);
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/config/ConfigLoader.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.config;
/** Config loader interface that load Tsunami configs from certain data sources. */
public interface ConfigLoader {
/**
* Load a {@link TsunamiConfig} object from certain data source.
*
* @return the loaded {@link TsunamiConfig} object.
*/
TsunamiConfig loadConfig();
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/config/ConfigModule.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.config;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.flogger.GoogleLogger;
import com.google.inject.AbstractModule;
import io.github.classgraph.ClassInfo;
import io.github.classgraph.ScanResult;
/**
* A Guice module that binds all Tsunami config objects at runtime.
*
* <p>This module relies on the {@link io.github.classgraph.ClassGraph} scan results to identify all
* Tsunami config objects annotated by the {@link
* com.google.tsunami.common.config.annotations.ConfigProperties} annotation. Each config class is
* bound to a singleton object whose fields are populated from the Tsunami config file.
*/
public final class ConfigModule extends AbstractModule {
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
private static final String CONFIG_PROPERTIES_ANNOTATION =
"com.google.tsunami.common.config.annotations.ConfigProperties";
private final ScanResult scanResult;
private final TsunamiConfig tsunamiConfig;
public ConfigModule(ScanResult scanResult, TsunamiConfig tsunamiConfig) {
this.scanResult = checkNotNull(scanResult);
this.tsunamiConfig = checkNotNull(tsunamiConfig);
}
@Override
protected void configure() {
bind(TsunamiConfig.class).toInstance(tsunamiConfig);
for (ClassInfo configClass :
scanResult
.getClassesWithAnnotation(CONFIG_PROPERTIES_ANNOTATION)
.filter(classInfo -> !classInfo.isAbstract())) {
logger.atInfo().log("Found Tsunami config class: %s", configClass.getName());
bindConfigClass(getConfigPrefix(configClass), configClass.loadClass());
}
}
private <T> void bindConfigClass(String configPrefix, Class<T> configClass) {
T configObject = tsunamiConfig.getConfig(configPrefix, configClass);
bind(configClass).toInstance(configObject);
}
private static String getConfigPrefix(ClassInfo configClass) {
Object configPrefix =
configClass
.getAnnotationInfo(CONFIG_PROPERTIES_ANNOTATION)
.getParameterValues()
.getValue("value");
if (!(configPrefix instanceof String)) {
throw new AssertionError("SHOULD NEVER HAPPEN, ConfigProperties value is not a string.");
}
return (String) configPrefix;
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/config/TsunamiConfig.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.config;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.CaseFormat;
import com.google.common.base.Converter;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Optional;
/** A data holder for all Tsunami config data, including config files and Java system properties. */
public final class TsunamiConfig {
private static final Converter<String, String> FIELD_NAME_TO_LOWER_UNDERSCORE =
CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.LOWER_UNDERSCORE);
private static final Splitter CONFIG_PATH_SPLITTER = Splitter.on('.').omitEmptyStrings();
private final ImmutableMap<String, Object> rawConfigData;
private TsunamiConfig(ImmutableMap<String, Object> rawConfigData) {
this.rawConfigData = checkNotNull(rawConfigData);
}
public ImmutableMap<String, Object> getRawConfigData() {
return rawConfigData;
}
public static TsunamiConfig fromYamlData(Map<String, Object> yamlConfig) {
return new TsunamiConfig(
yamlConfig == null ? ImmutableMap.of() : ImmutableMap.copyOf(yamlConfig));
}
public static Optional<String> getSystemProperty(String propertyName) {
return Optional.ofNullable(getSystemProperty(propertyName, null));
}
public static String getSystemProperty(String propertyName, String def) {
return System.getProperty(propertyName, def);
}
/**
* Get a config object with the given {@code configPrefix} and bind all config values to the
* requested {@code clazz}.
*
* <p>This code uses reflection to create the requested config object. The request type {@code T}
* must provide a no-argument or default constructor.
*
* @param configPrefix the prefix of the config to be read from.
* @param clazz the class of the returned config object.
* @param <T> actual config object type.
* @return an object whose field values are filled by the config data under the given {@code
* configPrefix}.
*/
public <T> T getConfig(String configPrefix, Class<T> clazz) {
checkNotNull(configPrefix);
checkNotNull(clazz);
Map<String, Object> configValue = readConfigValue(configPrefix);
return newConfigObject(clazz, configValue);
}
@SuppressWarnings("unchecked") // We know Map key is always String from yaml file.
public ImmutableMap<String, Object> readConfigValue(String configPrefix) {
Map<String, Object> retrievedData = rawConfigData;
// Config prefixes are dot separated words list, e.g. example.config.prefix.
for (String configKey : CONFIG_PATH_SPLITTER.split(configPrefix)) {
// Requested data not found under configPrefix.
if (!retrievedData.containsKey(configKey)) {
return ImmutableMap.of();
}
Object configData = retrievedData.get(configKey);
if (!(configData instanceof Map)) {
throw new ConfigException(
String.format(
"Unexpected data type for config '%s', expected '%s', got '%s'",
configKey, Map.class, configData.getClass()));
}
retrievedData = (Map<String, Object>) configData;
}
return ImmutableMap.copyOf(retrievedData);
}
private static <T> T newConfigObject(Class<T> clazz, Map<String, Object> configValue) {
try {
Constructor<T> configObjectCtor = clazz.getDeclaredConstructor();
// Always create an instance of the config data regardless of scope.
configObjectCtor.setAccessible(true);
T configObject = configObjectCtor.newInstance();
// Fill each field of the configObject from configValue using the field name as key.
for (Field field : clazz.getDeclaredFields()) {
String fieldName = field.getName();
if (configValue.containsKey(fieldName)
|| configValue.containsKey(FIELD_NAME_TO_LOWER_UNDERSCORE.convert(fieldName))) {
Object fieldValue =
Optional.ofNullable(configValue.get(fieldName))
.orElse(configValue.get(FIELD_NAME_TO_LOWER_UNDERSCORE.convert(fieldName)));
field.setAccessible(true);
field.set(configObject, fieldValue);
}
}
return configObject;
} catch (ReflectiveOperationException e) {
// This is bad. Config objects cannot be created or config value cannot be assigned to the
// field, we throw assertion error and fail the execution.
throw new AssertionError(
String.format(
"Unable to create new instance of '%s' using config value '%s'", clazz, configValue),
e);
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/config/YamlConfigLoader.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.config;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.flogger.GoogleLogger;
import com.google.common.io.Files;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Map;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
/** A {@link ConfigLoader} implementation that loads Tsunami configs from YAML file. */
public final class YamlConfigLoader implements ConfigLoader {
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
private static final String DEFAULT_CONFIG_FILE = "tsunami.yaml";
@Override
public TsunamiConfig loadConfig() {
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
Map<String, Object> rawYamlData = yaml.load(configFileReader());
return TsunamiConfig.fromYamlData(rawYamlData);
}
private static Reader configFileReader() {
String configFile =
TsunamiConfig.getSystemProperty("tsunami.config.location").orElse(DEFAULT_CONFIG_FILE);
try {
return Files.newReader(new File(configFile), UTF_8);
} catch (FileNotFoundException e) {
logger.atWarning().log(
"Unable to read config file '%s', default to empty config.", configFile);
return new StringReader("");
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/config/annotations/ConfigProperties.java
================================================
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.config.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* An annotation for marking a Tsunami config object that can be initialized from external config
* files, e.g. a {@code .yaml} file.
*
* <p>This annotation is required for any config object in order for Tsunami initialization logic to
* identify and automatically populate config properties.
*
* Example usage:
*
* <pre>{@code
* {@literal @}ConfigProperties("example.config.location")})
* public class ExampleConfig {
* // ...
* }
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ConfigProperties {
/**
* The required prefix of the properties that should be bound to the annotated object.
*
* <p>A valid prefix is defined as dot separated words list (e.g. "plugin.example.abc"). Each dot
* separated segment represents a section within the config file. For example, given a YAML file
*
* <pre>{@code
* plugin:
* example:
* abc:
* fieldA: valueA
* fieldB: valueB
* xyz:
* fieldC: valueC
* }</pre>
*
* value {@code "plugin.example.abc"} will select {@code fieldA} and {@code fieldB} for config
* binding for the annotated class.
*
* @return the prefix of the config properties.
*/
String value();
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/data/NetworkEndpointUtils.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For any utility update, please consider if Python's network endpoint utils
* (plugin_server/py/common/data/network_endpoint_utils.py) also needs the modification.
*/
package com.google.tsunami.common.data;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.net.HostAndPort;
import com.google.common.net.InetAddresses;
import com.google.tsunami.proto.AddressFamily;
import com.google.tsunami.proto.Hostname;
import com.google.tsunami.proto.IpAddress;
import com.google.tsunami.proto.NetworkEndpoint;
import com.google.tsunami.proto.Port;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
/** Static utility methods pertaining to {@link NetworkEndpoint} proto buffer. */
public final class NetworkEndpointUtils {
public static final int MAX_PORT_NUMBER = 65535;
private NetworkEndpointUtils() {}
public static boolean hasIpAddress(NetworkEndpoint networkEndpoint) {
return networkEndpoint.getType().equals(NetworkEndpoint.Type.IP)
|| networkEndpoint.getType().equals(NetworkEndpoint.Type.IP_PORT)
|| networkEndpoint.getType().equals(NetworkEndpoint.Type.IP_HOSTNAME)
|| networkEndpoint.getType().equals(NetworkEndpoint.Type.IP_HOSTNAME_PORT);
}
public static boolean hasHostname(NetworkEndpoint networkEndpoint) {
return networkEndpoint.getType().equals(NetworkEndpoint.Type.HOSTNAME)
|| networkEndpoint.getType().equals(NetworkEndpoint.Type.HOSTNAME_PORT)
|| networkEndpoint.getType().equals(NetworkEndpoint.Type.IP_HOSTNAME)
|| networkEndpoint.getType().equals(NetworkEndpoint.Type.IP_HOSTNAME_PORT);
}
public static boolean hasPort(NetworkEndpoint networkEndpoint) {
return networkEndpoint.getType().equals(NetworkEndpoint.Type.IP_PORT)
|| networkEndpoint.getType().equals(NetworkEndpoint.Type.HOSTNAME_PORT)
|| networkEndpoint.getType().equals(NetworkEndpoint.Type.IP_HOSTNAME_PORT);
}
public static boolean isIpV6Endpoint(NetworkEndpoint networkEndpoint) {
return hasIpAddress(networkEndpoint)
&& networkEndpoint.getIpAddress().getAddressFamily().equals(AddressFamily.IPV6);
}
/**
* Converts the given {@link NetworkEndpoint} to its uri authority representation.
*
* <p>For example:
*
* <ul>
* <li>ip_v4 = "1.2.3.4" -> uri = "1.2.3.4"
* <li>ip_v6 = "3ffe::1" -> uri = "[3ffe::1]"
* <li>host = "localhost" -> url = "localhost"
* <li>ip_v4 = "1.2.3.4", port = 8888 -> uri = "1.2.3.4:8888"
* <li>ip_v6 = "3ffe::1", port = 8888 -> uri = "[3ffe::1]:8888"
* <li>host = "localhost", port = 8888 -> url = "localhost:8888"
* </ul>
*
* @param networkEndpoint the {@link NetworkEndpoint} instance to be converted.
* @return the URI authority converted from the {@link NetworkEndpoint} instance.
*/
public static String toUriAuthority(NetworkEndpoint networkEndpoint) {
return toHostAndPort(networkEndpoint).toString();
}
public static HostAndPort toHostAndPort(NetworkEndpoint networkEndpoint) {
switch (networkEndpoint.getType()) {
case IP:
return HostAndPort.fromHost(networkEndpoint.getIpAddress().getAddress());
case IP_PORT:
return HostAndPort.fromParts(
networkEndpoint.getIpAddress().getAddress(), networkEndpoint.getPort().getPortNumber());
case HOSTNAME:
case IP_HOSTNAME:
return HostAndPort.fromHost(networkEndpoint.getHostname().getName());
case HOSTNAME_PORT:
case IP_HOSTNAME_PORT:
return HostAndPort.fromParts(
networkEndpoint.getHostname().getName(), networkEndpoint.getPort().getPortNumber());
case UNRECOGNIZED:
case TYPE_UNSPECIFIED:
throw new AssertionError("Type for NetworkEndpoint must be specified.");
}
throw new AssertionError(
String.format(
"Should never happen. Unchecked NetworkEndpoint type: %s", networkEndpoint.getType()));
}
/**
* Creates a {@link NetworkEndpoint} proto buffer object from the given ip address.
*
* @param ipAddress the IP address of the network endpoint.
* @return the created {@link NetworkEndpoint} instance from the given IP address.
*/
public static NetworkEndpoint forIp(String ipAddress) {
checkArgument(InetAddresses.isInetAddress(ipAddress), "'%s' is not an IP address.", ipAddress);
return NetworkEndpoint.newBuilder()
.setType(NetworkEndpoint.Type.IP)
.setIpAddress(
IpAddress.newBuilder()
.setAddressFamily(ipAddressFamily(ipAddress))
.setAddress(ipAddress))
.build();
}
/**
* Creates a {@link NetworkEndpoint} proto buffer object from the given ip address and port.
*
* @param ipAddress the IP address of the network endpoint.
* @param port the port number of the network endpoint
* @return the created {@link NetworkEndpoint} instance from the given IP and port.
*/
public static NetworkEndpoint forIpAndPort(String ipAddress, int port) {
checkArgument(InetAddresses.isInetAddress(ipAddress), "'%s' is not an IP address.", ipAddress);
checkArgument(
0 <= port && port <= MAX_PORT_NUMBER,
"Port out of range. Expected [0, %s], actual %s.",
MAX_PORT_NUMBER,
port);
return forIp(ipAddress).toBuilder()
.setType(NetworkEndpoint.Type.IP_PORT)
.setPort(Port.newBuilder().setPortNumber(port))
.build();
}
/**
* Creates a {@link NetworkEndpoint} proto buffer object from the given hostname.
*
* @param hostname the hostname of the network endpoint
* @return the created {@link NetworkEndpoint} instance from the hostname.
*/
public static NetworkEndpoint forHostname(String hostname) {
checkArgument(
!InetAddresses.isInetAddress(hostname), "Expected hostname, got IP address '%s'", hostname);
return NetworkEndpoint.newBuilder()
.setType(NetworkEndpoint.Type.HOSTNAME)
.setHostname(Hostname.newBuilder().setName(hostname))
.build();
}
/**
* Creates a {@link NetworkEndpoint} proto buffer object from the given ip address and hostname.
*
* @param hostname the hostname of the network endpoint
* @param ipAddress the IP address of the network endpoint.
* @return the created {@link NetworkEndpoint} instance from the IP address and hostname.
*/
public static NetworkEndpoint forIpAndHostname(String ipAddress, String hostname) {
return forIp(ipAddress).toBuilder()
.setType(NetworkEndpoint.Type.IP_HOSTNAME)
.setHostname(Hostname.newBuilder().setName(hostname))
.build();
}
/**
* Creates a {@link NetworkEndpoint} proto buffer object from the given hostname and port.
*
* @param hostname the hostname of the network endpoint
* @param port the port number of the network endpoint.
* @return the created {@link NetworkEndpoint} instance from the hostname and port.
*/
public static NetworkEndpoint forHostnameAndPort(String hostname, int port) {
checkArgument(
0 <= port && port <= MAX_PORT_NUMBER,
"Port out of range. Expected [0, %s], actual %s.",
MAX_PORT_NUMBER,
port);
return forHostname(hostname).toBuilder()
.setType(NetworkEndpoint.Type.HOSTNAME_PORT)
.setPort(Port.newBuilder().setPortNumber(port))
.build();
}
/**
* Returns a {@link NetworkEndpoint} proto buffer object from the given ip address, hostname and
* port.
*
* @param ipAddress the IP address of the network endpoint.
* @param hostname the hostname of the network endpoint
* @param port the port number of the network endpoint.
* @return the created {@link NetworkEndpoint} instance from the parameters.
*/
public static NetworkEndpoint forIpHostnameAndPort(String ipAddress, String hostname, int port) {
checkArgument(
0 <= port && port <= MAX_PORT_NUMBER,
"Port out of range. Expected [0, %s], actual %s.",
MAX_PORT_NUMBER,
port);
return forIpAndHostname(ipAddress, hostname).toBuilder()
.setType(NetworkEndpoint.Type.IP_HOSTNAME_PORT)
.setPort(Port.newBuilder().setPortNumber(port))
.build();
}
/**
* Returns a {@link NetworkEndpoint} proto buffer object from the given {@code networkEndpoint}
* and port. The {@code networkEndpoint} parameter cannot contain any port information, otherwise
* {@link IllegalArgumentException} is thrown.
*
* @param networkEndpoint the source {@link NetworkEndpoint} instance without the port number
* @param port the port number of the network endpoint.
* @return the {@link NetworkEndpoint} instance from the parameters.
*/
public static NetworkEndpoint forNetworkEndpointAndPort(
NetworkEndpoint networkEndpoint, int port) {
checkNotNull(networkEndpoint);
checkArgument(
0 <= port && port <= MAX_PORT_NUMBER,
"Port out of range. Expected [0, %s], actual %s.",
MAX_PORT_NUMBER,
port);
switch (networkEndpoint.getType()) {
case IP:
return networkEndpoint.toBuilder()
.setType(NetworkEndpoint.Type.IP_PORT)
.setPort(Port.newBuilder().setPortNumber(port))
.build();
case HOSTNAME:
return networkEndpoint.toBuilder()
.setType(NetworkEndpoint.Type.HOSTNAME_PORT)
.setPort(Port.newBuilder().setPortNumber(port))
.build();
case IP_HOSTNAME:
return networkEndpoint.toBuilder()
.setType(NetworkEndpoint.Type.IP_HOSTNAME_PORT)
.setPort(Port.newBuilder().setPortNumber(port))
.build();
case IP_PORT:
case HOSTNAME_PORT:
case IP_HOSTNAME_PORT:
case UNRECOGNIZED:
case TYPE_UNSPECIFIED:
throw new IllegalArgumentException("Invalid NetworkEndpoint type.");
}
throw new AssertionError(
String.format(
"Should never happen. Unchecked NetworkEndpoint type: %s", networkEndpoint.getType()));
}
public static AddressFamily ipAddressFamily(String ipAddress) {
InetAddress inetAddress = InetAddresses.forString(ipAddress);
if (inetAddress instanceof Inet4Address) {
return AddressFamily.IPV4;
} else if (inetAddress instanceof Inet6Address) {
return AddressFamily.IPV6;
} else {
throw new AssertionError(String.format("Unknown IP address family for IP '%s'", ipAddress));
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/data/NetworkServiceUtils.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For any utility update, please consider if Python's network service utils
* (plugin_server/py/common/data/network_service_utils.py) also needs the modification.
*/
package com.google.tsunami.common.data;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableMap;
import com.google.tsunami.proto.AddressFamily;
import com.google.tsunami.proto.Hostname;
import com.google.tsunami.proto.IpAddress;
import com.google.tsunami.proto.NetworkEndpoint;
import com.google.tsunami.proto.NetworkService;
import com.google.tsunami.proto.Port;
import com.google.tsunami.proto.ServiceContext;
import com.google.tsunami.proto.TransportProtocol;
import com.google.tsunami.proto.WebServiceContext;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.Optional;
/** Static utility methods pertaining to {@link NetworkService} proto buffer. */
public final class NetworkServiceUtils {
// Service names are those described in [RFC6335].
private static final ImmutableMap<String, Boolean> IS_PLAIN_HTTP_BY_KNOWN_WEB_SERVICE_NAME =
ImmutableMap.<String, Boolean>builder()
.put("http", true)
.put("http-alt", true) // Some http server are identified as this rather than "http".
.put("http-proxy", true)
.put("https", false)
.put("radan-http", true) // Port 8088, Hadoop Yarn web UI identified as this.
.put("ssl/http", false)
.put("ssl/https", false)
.put("ssl/http-proxy", false)
.put("ssl/tungsten-https", false) // Port 9443, WSO2 Identity Server & WSO2 API Manager.
.put("ssl/wso2esb-console", false) // Port 9444, WSO2 Identity Server Analytics.
.build();
private NetworkServiceUtils() {}
public static boolean isWebService(Optional<String> serviceName) {
return serviceName.isPresent()
&& IS_PLAIN_HTTP_BY_KNOWN_WEB_SERVICE_NAME.containsKey(
Ascii.toLowerCase(serviceName.get()));
}
public static boolean isWebService(NetworkService networkService) {
checkNotNull(networkService);
// A web-service is a service that is either flagged as http by nmap or one that supports at
// least one HTTP method.
return (networkService.getSupportedHttpMethodsCount() > 0)
|| isWebService(Optional.of(networkService.getServiceName()));
}
public static boolean isPlainHttp(NetworkService networkService) {
checkNotNull(networkService);
var isWebService = isWebService(networkService);
var isKnownServiceName = IS_PLAIN_HTTP_BY_KNOWN_WEB_SERVICE_NAME.containsKey(
Ascii.toLowerCase(networkService.getServiceName()));
var doesNotSupportAnySslVersion = networkService.getSupportedSslVersionsCount() == 0;
if (!isKnownServiceName) {
return isWebService && doesNotSupportAnySslVersion;
}
var isKnownPlainHttpService =
IS_PLAIN_HTTP_BY_KNOWN_WEB_SERVICE_NAME.getOrDefault(
Ascii.toLowerCase(networkService.getServiceName()), false);
return isKnownPlainHttpService && doesNotSupportAnySslVersion;
}
public static String getServiceName(NetworkService networkService) {
if (isWebService(networkService) && networkService.hasSoftware()) {
return Ascii.toLowerCase(networkService.getSoftware().getName());
}
return Ascii.toLowerCase(networkService.getServiceName());
}
public static String getWebServiceName(NetworkService networkService) {
if (isWebService(networkService)
&& networkService.getServiceContext().getWebServiceContext().hasSoftware()) {
return Ascii.toLowerCase(
networkService.getServiceContext().getWebServiceContext().getSoftware().getName());
}
return Ascii.toLowerCase(networkService.getServiceName());
}
public static NetworkService buildUriNetworkService(String uriString) {
try {
URI uri = new URI(uriString);
NetworkEndpoint uriEndPoint = buildUriNetworkEndPoint(uri);
return NetworkService.newBuilder()
.setNetworkEndpoint(uriEndPoint)
.setTransportProtocol(TransportProtocol.TCP)
.setServiceName(uri.getScheme())
.setServiceContext(
ServiceContext.newBuilder()
.setWebServiceContext(
WebServiceContext.newBuilder().setApplicationRoot(uri.getPath())))
.build();
} catch (URISyntaxException exception) {
throw new AssertionError(
String.format(
"Invalid uri syntax passed as target '%s'. Error: %s", uriString, exception));
}
}
private static NetworkEndpoint buildUriNetworkEndPoint(URI uri) {
try {
String hostname = uri.getHost();
String scheme = uri.getScheme();
checkArgument(
scheme.equals("http") || scheme.equals("https"),
"Uri scheme should be one of the following: 'http', 'https'");
int port = uri.getPort();
if (port < 0) {
port = scheme.equals("http") ? 80 : 443;
}
String ipAddress = InetAddress.getByName(hostname).getHostAddress();
InetAddress inetAddress = InetAddress.getByName(uri.getHost());
checkArgument(
(inetAddress instanceof Inet4Address) || (inetAddress instanceof Inet6Address),
"Invalid address family");
AddressFamily addressFamily =
inetAddress instanceof Inet4Address ? AddressFamily.IPV4 : AddressFamily.IPV6;
return NetworkEndpoint.newBuilder()
.setType(NetworkEndpoint.Type.IP_HOSTNAME_PORT)
.setPort(Port.newBuilder().setPortNumber(port))
.setHostname(Hostname.newBuilder().setName(uri.getHost()))
.setIpAddress(
IpAddress.newBuilder().setAddressFamily(addressFamily).setAddress(ipAddress))
.build();
} catch (UnknownHostException exception) {
throw new AssertionError(
String.format("Unable to get valid host from uri. Error: %s", exception));
}
}
/**
* Build the root url for a web application service.
*
* @param networkService a web (http/https) service
* @return the root url for the web service, which always ends with a <code>"/"</code>.
*/
public static String buildWebApplicationRootUrl(NetworkService networkService) {
checkNotNull(networkService);
if (!isWebService(networkService)) {
return "http://"
+ NetworkEndpointUtils.toUriAuthority(networkService.getNetworkEndpoint())
+ "/";
}
String rootUrl =
(isPlainHttp(networkService) ? "http://" : "https://")
+ buildWebUriAuthority(networkService)
+ buildWebAppRootPath(networkService);
return rootUrl.endsWith("/") ? rootUrl : rootUrl + "/";
}
private static String buildWebAppRootPath(NetworkService networkService) {
String rootPath =
networkService.getServiceContext().hasWebServiceContext()
? networkService.getServiceContext().getWebServiceContext().getApplicationRoot()
: "/";
if (!rootPath.startsWith("/")) {
rootPath = "/" + rootPath;
}
return rootPath;
}
private static String buildWebUriAuthority(NetworkService networkService) {
String uriAuthority = NetworkEndpointUtils.toUriAuthority(networkService.getNetworkEndpoint());
// Remove default ports of the protocol.
boolean isPlainHttp = isPlainHttp(networkService);
if (isPlainHttp && uriAuthority.endsWith(":80")) {
uriAuthority = uriAuthority.substring(0, uriAuthority.lastIndexOf(":80"));
}
if (!isPlainHttp && uriAuthority.endsWith(":443")) {
uriAuthority = uriAuthority.substring(0, uriAuthority.lastIndexOf(":443"));
}
return uriAuthority;
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/Archiver.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.io.archiving;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
/** An {@link Archiver} archives the given data to some data storage. */
public interface Archiver {
/**
* Archives the {@code data} associated with the given {@code name}.
*
* @param name the name that will be associated with the data
* @param data the data to be archived in byte array format
* @return whether the given data is archived successfully.
*/
@CanIgnoreReturnValue
boolean archive(String name, byte[] data);
/**
* Archives the {@code data} associated with the given {@code name}. By default, this method
* encodes the {@link CharSequence} {@code data} into a sequence of bytes using {@code UTF_8}
* {@link java.nio.charset.StandardCharsets} and calls the {@link #archive(String, byte[])}
* method.
*
* @param name the name that will be associated with the data
* @param data the data to be archived in {@link CharSequence} format
* @return whether the given data is archived successfully.
*/
@CanIgnoreReturnValue
default boolean archive(String name, CharSequence data) {
return archive(name, checkNotNull(data).toString().getBytes(UTF_8));
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/GoogleCloudStorageArchiver.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.io.archiving;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.beust.jcommander.validators.PositiveInteger;
import com.google.cloud.WriteChannel;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Storage;
import com.google.common.flogger.GoogleLogger;
import com.google.inject.assistedinject.Assisted;
import com.google.tsunami.common.cli.CliOption;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
/** An {@link Archiver} implementation that archives data into Google Cloud Storage. */
public class GoogleCloudStorageArchiver implements Archiver {
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
// For sanity-checking and to parse out the bucket name and object id.
// See https://cloud.google.com/storage/docs/bucket-naming
public static final Pattern GS_URL_PATTERN = Pattern.compile("gs://([^/]{3,63})/(.*)");
private final Options options;
private final Storage storage;
/** All command line options for {@link GoogleCloudStorageArchiver}. */
@Parameters(separators = "=")
public static final class Options implements CliOption {
@Parameter(
names = "--gcs-archiver-chunk-size-in-bytes",
description = "The size of the data chunk when GCS archiver uploads data to Cloud Storage.",
validateWith = PositiveInteger.class)
int chunkSizeInBytes = 1_000;
@Parameter(
names = "--gcs-archiver-chunk-upload-threshold-in-bytes",
description = "The default data size threshold in bytes to enable chunk upload to GCS.",
validateWith = PositiveInteger.class)
int chunkUploadThresholdInBytes = 1_000_000;
@Override
public void validate() {}
}
@Inject
public GoogleCloudStorageArchiver(Options options, @Assisted Storage storage) {
this.options = checkNotNull(options);
this.storage = checkNotNull(storage);
}
private static BlobInfo parseBlobInfo(String gcsUrl) {
Matcher matcher = GS_URL_PATTERN.matcher(gcsUrl);
checkArgument(matcher.matches(), "Invalid GCS URL: '%s'", gcsUrl);
String bucketName = matcher.group(1);
String objectName = matcher.group(2);
return BlobInfo.newBuilder(bucketName, objectName).build();
}
@Override
public boolean archive(String gcsUrl, byte[] data) {
BlobInfo blobInfo = parseBlobInfo(gcsUrl);
if (data.length <= options.chunkUploadThresholdInBytes) {
// Create the blob in one request.
logger.atInfo().log("Archiving data to GCS at '%s' in one request.", gcsUrl);
storage.create(blobInfo, data);
return true;
}
// When content is large (1MB or more) it is recommended to write it in chunks via the blob's
// channel writer.
logger.atInfo().log(
"Content is larger than threshold, archiving data to GCS at '%s' in chunks.", gcsUrl);
try (WriteChannel writer = storage.writer(blobInfo)) {
for (int chunkOffset = 0;
chunkOffset < data.length;
chunkOffset += options.chunkSizeInBytes) {
int chunkSize = Math.min(data.length - chunkOffset, options.chunkSizeInBytes);
writer.write(ByteBuffer.wrap(data, chunkOffset, chunkSize));
}
return true;
} catch (IOException e) {
logger.atSevere().withCause(e).log("Unable to archving data to GCS at '%s'.", gcsUrl);
return false;
}
}
/** The factory of {@link GoogleCloudStorageArchiver} types for usage with assisted injection. */
// TODO(b/145315535): consider wrap the Storage API into a client library. Current implementation
// is not easily testable.
public interface Factory {
GoogleCloudStorageArchiver create(Storage storage);
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/GoogleCloudStorageArchiverModule.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.io.archiving;
import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryModuleBuilder;
/** Installs {@link GoogleCloudStorageArchiver}. */
public class GoogleCloudStorageArchiverModule extends AbstractModule {
@Override
protected void configure() {
install(new FactoryModuleBuilder().build(GoogleCloudStorageArchiver.Factory.class));
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/RawFileArchiver.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.io.archiving;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Strings;
import com.google.common.flogger.GoogleLogger;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
/** An {@link Archiver} implementation that archives data into file systems as raw files. */
public class RawFileArchiver implements Archiver {
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
@Override
public boolean archive(String fileName, byte[] data) {
checkArgument(!Strings.isNullOrEmpty(fileName));
checkNotNull(data);
try {
logger.atInfo().log("Archiving data to file system with filename '%s'.", fileName);
Files.asByteSink(new File(fileName)).write(data);
return true;
} catch (IOException e) {
logger.atWarning().withCause(e).log("Failed archiving data to file '%s'.", fileName);
return false;
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeArchiver.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.io.archiving.testing;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.Maps;
import com.google.tsunami.common.io.archiving.Archiver;
import java.util.Collection;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/** An implementation of {@link Archiver} that stores data in memory for testing purposes. */
public final class FakeArchiver implements Archiver {
private final Map<String, byte[]> archivedByteArrayData = Maps.newHashMap();
private final Map<String, CharSequence> archivedCharSequenceData = Maps.newHashMap();
private boolean shouldFail = false;
@Override
public boolean archive(String name, byte[] data) {
if (shouldFail) {
return false;
}
archivedByteArrayData.put(name, data);
return true;
}
@Override
public boolean archive(String name, CharSequence data) {
if (shouldFail) {
return false;
}
archivedCharSequenceData.put(name, data);
return true;
}
public void failArchival() {
this.shouldFail = true;
}
public byte[] getStoredByteArrays(String name) {
if (!archivedByteArrayData.containsKey(name)) {
throw new NoSuchElementException(String.format("'%s' not found in FakeArchiver", name));
}
return archivedByteArrayData.get(name);
}
public CharSequence getStoredCharSequence(String name) {
if (!archivedCharSequenceData.containsKey(name)) {
throw new NoSuchElementException(String.format("'%s' not found in FakeArchiver", name));
}
return archivedCharSequenceData.get(name);
}
public void assertNoByteArraysStored() {
assertThat(archivedByteArrayData).isEmpty();
}
public void assertNoCharSequencesStored() {
assertThat(archivedCharSequenceData).isEmpty();
}
public void assertNoDataStored() {
assertNoByteArraysStored();
assertNoCharSequencesStored();
}
public void assertByteArraysStored(Map<String, byte[]> expectedData) {
assertThat(archivedByteArrayData).containsExactlyEntriesIn(expectedData);
}
public void assertByteArraysStoredForNames(Set<String> expectedNames) {
assertThat(archivedByteArrayData.keySet()).containsExactlyElementsIn(expectedNames);
}
public void assertByteArraysStoredWithValues(Collection<byte[]> expectedValues) {
assertThat(archivedByteArrayData.values()).containsExactlyElementsIn(expectedValues);
}
public void assertCharSequencesStored(Map<String, CharSequence> expectedData) {
assertThat(archivedCharSequenceData).containsExactlyEntriesIn(expectedData);
}
public void assertCharSequencesStoredForNames(Set<String> expectedNames) {
assertThat(archivedCharSequenceData.keySet()).containsExactlyElementsIn(expectedNames);
}
public void assertCharSequencesStoredWithValues(Collection<CharSequence> expectedValues) {
assertThat(archivedCharSequenceData.values()).containsExactlyElementsIn(expectedValues);
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeGoogleCloudStorageArchivers.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.io.archiving.testing;
import com.google.cloud.storage.Storage;
import com.google.tsunami.common.io.archiving.GoogleCloudStorageArchiver;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
/** A collection of fake {@link GoogleCloudStorageArchiver} created by {@link FakeFactory}. */
public final class FakeGoogleCloudStorageArchivers {
private final Map<Storage, FakeArchiver> delegatedArchivers = new HashMap<>();
public void assertNoDataStored() {
for (FakeArchiver delegate : delegatedArchivers.values()) {
delegate.assertNoDataStored();
}
}
/**
* Get the byte array data stored in {@code storage} at {@code gcsUrl}.
*
* @param storage the instance of the GCS storage.
* @param gcsUrl the URL to the GCS storage object.
* @return the content of the GCS storage object in byte array format.
*/
public byte[] getStoredByteArrays(Storage storage, String gcsUrl) {
if (!delegatedArchivers.containsKey(storage)) {
throw new NoSuchElementException(String.format("Storage '%s' not found", storage));
}
return delegatedArchivers.get(storage).getStoredByteArrays(gcsUrl);
}
/**
* Get the {@link CharSequence} data stored in {@code storage} at {@code gcsUrl}.
*
* @param storage the instance of the GCS storage.
* @param gcsUrl the URL to the GCS storage object.
* @return the content of the GCS storage object in {@link CharSequence} format.
*/
public CharSequence getStoredCharSequence(Storage storage, String gcsUrl) {
if (!delegatedArchivers.containsKey(storage)) {
throw new NoSuchElementException(String.format("Storage '%s' not found", storage));
}
return delegatedArchivers.get(storage).getStoredCharSequence(gcsUrl);
}
final class FakeGoogleCloudStorageArchiver extends GoogleCloudStorageArchiver {
private final Storage storage;
private FakeGoogleCloudStorageArchiver(Storage storage) {
super(new Options(), storage);
this.storage = storage;
}
@Override
public boolean archive(String gcsUrl, byte[] data) {
FakeArchiver fakeArchiver =
delegatedArchivers.computeIfAbsent(storage, unused -> new FakeArchiver());
return fakeArchiver.archive(gcsUrl, data);
}
@Override
public boolean archive(String gcsUrl, CharSequence data) {
FakeArchiver fakeArchiver =
delegatedArchivers.computeIfAbsent(storage, unused -> new FakeArchiver());
return fakeArchiver.archive(gcsUrl, data);
}
}
final class FakeFactory implements GoogleCloudStorageArchiver.Factory {
@Override
public GoogleCloudStorageArchiver create(Storage storage) {
return new FakeGoogleCloudStorageArchiver(storage);
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeGoogleCloudStorageArchiversModule.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.io.archiving.testing;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.tsunami.common.io.archiving.GoogleCloudStorageArchiver;
import javax.inject.Singleton;
/** Installs fake factory for {@link GoogleCloudStorageArchiver}. */
public final class FakeGoogleCloudStorageArchiversModule extends AbstractModule {
@Provides
@Singleton
GoogleCloudStorageArchiver.Factory provideGoogleCloudStorageArchiverFactory(
FakeGoogleCloudStorageArchivers fakeGoogleCloudStorageArchivers) {
return fakeGoogleCloudStorageArchivers.new FakeFactory();
}
@Provides
@Singleton
FakeGoogleCloudStorageArchivers provideFakeGoogleCloudStorageArchivers() {
return new FakeGoogleCloudStorageArchivers();
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeRawFileArchiver.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.io.archiving.testing;
import com.google.tsunami.common.io.archiving.RawFileArchiver;
/** A fake implementation of the {@link RawFileArchiver}. */
public final class FakeRawFileArchiver extends RawFileArchiver {
private final FakeArchiver delegate = new FakeArchiver();
@Override
public boolean archive(String fileName, byte[] data) {
return delegate.archive(fileName, data);
}
@Override
public boolean archive(String fileName, CharSequence data) {
return delegate.archive(fileName, data);
}
public byte[] getStoredByteArrays(String fileName) {
return delegate.getStoredByteArrays(fileName);
}
public CharSequence getStoredCharSequence(String fileName) {
return delegate.getStoredCharSequence(fileName);
}
public void assertNoDataStored() {
delegate.assertNoDataStored();
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeRawFileArchiverModule.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.io.archiving.testing;
import com.google.inject.AbstractModule;
import com.google.tsunami.common.io.archiving.RawFileArchiver;
import javax.inject.Singleton;
/** Installs {@link FakeRawFileArchiver}. */
public final class FakeRawFileArchiverModule extends AbstractModule {
@Override
protected void configure() {
// This is intentional to create 2 separate bindings. One is for FakeRawFileArchiver itself,
// which always injects as a singleton. The other one links the binding for RawFileArchiver to
// FakeRawFileArchiver so that the FakeRawFileArchiver singleton instance is injected to
// RawFileArchiver. This way the classes on the inheritance chain always get the same instance.
//
// This is useful in unit test. Test cases now are able to get the same injected instance as the
// code under test.
bind(FakeRawFileArchiver.class).in(Singleton.class);
bind(RawFileArchiver.class).to(FakeRawFileArchiver.class);
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/FuzzingUtils.java
================================================
/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.stream.Collectors.joining;
import com.google.auto.value.AutoValue;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.tsunami.common.net.http.HttpRequest;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/** Fuzzing utilities for HTTP request properties. */
public final class FuzzingUtils {
/* TODO(b/251480660): Refactor to generic fuzzing library. */
/**
* Fuzz GET parameters by replacing values with the provided payload. If no GET parameter is
* found, add a new parameter called {@code defaultParameter}.
*/
public static ImmutableList<HttpRequest> fuzzGetParametersWithDefaultParameter(
HttpRequest request, String payload, String defaultParameter) {
return fuzzGetParameters(request, payload, Optional.of(defaultParameter), ImmutableSet.of());
}
/**
* Fuzz GET parameters by replacing values with the provided payload. Payloads are expected to
* represent paths. If encountered, file extesions and path prefixes are kept and provided via
* additional exploit requests. If no GET parameter is found, return an empty list.
*/
public static ImmutableList<HttpRequest> fuzzGetParametersExpectingPathValues(
HttpRequest request, String payload) {
return fuzzGetParameters(
request, payload, Optional.empty(), ImmutableSet.of(FuzzingModifier.FUZZING_PATHS));
}
/**
* Fuzz GET parameters by replacing values with the provided payload. If no GET parameter is
* found, return an empty list.
*/
public static ImmutableList<HttpRequest> fuzzGetParameters(HttpRequest request, String payload) {
return fuzzGetParameters(request, payload, Optional.empty(), ImmutableSet.of());
}
private static ImmutableList<HttpRequest> fuzzGetParameters(
HttpRequest request,
String payload,
Optional<String> defaultParameter,
ImmutableSet<FuzzingModifier> modifiers) {
URI parsedUrl = URI.create(request.url());
ImmutableList<HttpQueryParameter> queryParams = parseQuery(parsedUrl.getQuery());
if (queryParams.isEmpty() && defaultParameter.isPresent()) {
return ImmutableList.of(
request.toBuilder()
.setUrl(
assembleUrlWithQueries(
parsedUrl,
ImmutableList.of(HttpQueryParameter.create(defaultParameter.get(), payload))))
.build());
}
return fuzzParams(queryParams, payload, modifiers).stream()
.map(fuzzedParams -> assembleUrlWithQueries(parsedUrl, fuzzedParams))
.map(fuzzedUrl -> request.toBuilder().setUrl(fuzzedUrl).build())
.collect(toImmutableList());
}
private static ImmutableList<HttpQueryParameter> setFuzzedParams(
ImmutableList<HttpQueryParameter> params, int index, String payload) {
List<HttpQueryParameter> paramsWithPayload = new ArrayList<>(params);
paramsWithPayload.set(index, HttpQueryParameter.create(params.get(index).name(), payload));
return ImmutableList.copyOf(paramsWithPayload);
}
private static void fuzzParamsWithExtendedPathPayloads(
ImmutableSet.Builder<ImmutableList<HttpQueryParameter>> builder,
ImmutableList<HttpQueryParameter> params,
int index,
String payload) {
int dotLocation = params.get(index).value().lastIndexOf('.');
if (dotLocation != -1) {
builder.add(
setFuzzedParams(
params, index, payload + "%00" + params.get(index).value().substring(dotLocation)));
}
int slashLocation = params.get(index).value().lastIndexOf('/');
if (slashLocation != -1) {
builder.add(
setFuzzedParams(
params, index, params.get(index).value().substring(0, slashLocation + 1) + payload));
}
if (dotLocation != -1 && slashLocation != -1 && slashLocation < dotLocation) {
builder.add(
setFuzzedParams(
params,
index,
params.get(index).value().substring(0, slashLocation + 1)
+ payload
+ "%00"
+ params.get(index).value().substring(dotLocation)));
}
}
private static ImmutableSet<ImmutableList<HttpQueryParameter>> fuzzParams(
ImmutableList<HttpQueryParameter> params,
String payload,
ImmutableSet<FuzzingModifier> modifiers) {
ImmutableSet.Builder<ImmutableList<HttpQueryParameter>> fuzzedParamsBuilder =
ImmutableSet.builder();
for (int i = 0; i < params.size(); i++) {
fuzzedParamsBuilder.add(setFuzzedParams(params, i, payload));
if (modifiers.contains(FuzzingModifier.FUZZING_PATHS)) {
fuzzParamsWithExtendedPathPayloads(fuzzedParamsBuilder, params, i, payload);
}
}
return fuzzedParamsBuilder.build();
}
public static ImmutableList<HttpQueryParameter> parseQuery(String query) {
if (isNullOrEmpty(query)) {
return ImmutableList.of();
}
ImmutableList.Builder<HttpQueryParameter> queryParamsBuilder = ImmutableList.builder();
for (String param : Splitter.on('&').split(query)) {
int equalPosition = param.indexOf("=");
if (equalPosition > -1) {
String name = param.substring(0, equalPosition);
String value = param.substring(equalPosition + 1);
queryParamsBuilder.add(HttpQueryParameter.create(name, value));
} else {
queryParamsBuilder.add(HttpQueryParameter.create(param, ""));
}
}
return queryParamsBuilder.build();
}
private static String assembleUrlWithQueries(
URI parsedUrl, ImmutableList<HttpQueryParameter> params) {
String query = assembleQueryParams(params);
StringBuilder urlBuilder = new StringBuilder();
urlBuilder.append(parsedUrl.getScheme()).append("://").append(parsedUrl.getRawAuthority());
if (!isNullOrEmpty(parsedUrl.getRawPath())) {
urlBuilder.append(parsedUrl.getRawPath());
}
if (!isNullOrEmpty(query)) {
urlBuilder.append('?').append(query);
}
if (!isNullOrEmpty(parsedUrl.getRawFragment())) {
urlBuilder.append('#').append(parsedUrl.getRawFragment());
}
return urlBuilder.toString();
}
private static String assembleQueryParams(ImmutableList<HttpQueryParameter> params) {
return params.stream()
.map(param -> String.format("%s=%s", param.name(), param.value()))
.collect(joining("&"));
}
/** URL Query parameter name and value pair. */
@AutoValue
public abstract static class HttpQueryParameter {
public abstract String name();
public abstract String value();
public static HttpQueryParameter create(String name, String value) {
return new AutoValue_FuzzingUtils_HttpQueryParameter(name, value);
}
}
enum FuzzingModifier {
FUZZING_PATHS;
}
private FuzzingUtils() {}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/UrlUtils.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
import okhttp3.HttpUrl;
/** Utilities for dealing with URLs. */
public final class UrlUtils {
private static final Joiner PATH_JOINER = Joiner.on("/");
private static final Pattern SLASH_PREFIX_PATTERN = Pattern.compile("^/+");
private static final Pattern TRAILING_SLASH_PATTERN = Pattern.compile("/+$");
/**
* Enumerates all sub-paths for a given URL. All query parameters and fragments are removed.
*
* <p>For example:
*
* <ul>
* <li>given <code>"http://localhost/"</code>, it returns <code>["http://localhost/"]</code>
* <li>given <code>"http://localhost/a/b/"</code>, it returns <code>
* ["http://localhost/", "http://localhost/a/", "http://localhost/a/b/"]</code>
* </ul>
*
* @param url the URL to be enumerated.
* @return all sub-paths URLs for the given URL.
*/
public static ImmutableSet<HttpUrl> allSubPaths(String url) {
return allSubPaths(HttpUrl.parse(url));
}
/**
* Enumerates all sub-paths for a given URL. All query parameters and fragments are removed.
*
* <p>For example:
*
* <ul>
* <li>given <code>"http://localhost/"</code>, it returns <code>["http://localhost/"]</code>
* <li>given <code>"http://localhost/a/b/"</code>, it returns <code>
* ["http://localhost/", "http://localhost/a/", "http://localhost/a/b/"]</code>
* </ul>
*
* @param url the URL to be enumerated.
* @return all sub-paths URLs for the given URL.
*/
public static ImmutableSet<HttpUrl> allSubPaths(HttpUrl url) {
if (url == null) {
return ImmutableSet.of();
}
// Url at root.
List<String> pathSegments = url.encodedPathSegments();
if (pathSegments.size() == 1 && pathSegments.get(0).isEmpty()) {
return ImmutableSet.of(url.newBuilder().query(null).fragment(null).build());
}
// Url has sub-paths.
ImmutableSet.Builder<HttpUrl> allSubUrlsBuilder = ImmutableSet.builder();
for (int pathEnd = 0; pathEnd <= pathSegments.size(); pathEnd++) {
List<String> subPathSegments = Lists.newArrayList(pathSegments.subList(0, pathEnd));
// Ensure sub-path has leading slash.
if (subPathSegments.isEmpty() || !subPathSegments.get(0).isEmpty()) {
subPathSegments.add(0, "");
}
// Ensure sub-path has trailing slash.
if (subPathSegments.size() == 1 || !Iterables.getLast(subPathSegments).isEmpty()) {
subPathSegments.add("");
}
allSubUrlsBuilder.add(
url.newBuilder()
.encodedPath(PATH_JOINER.join(subPathSegments))
.query(null)
.fragment(null)
.build());
}
return allSubUrlsBuilder.build();
}
/**
* Removes the leading slashes of a URL path.
*
* @param path the URL path to be transformed.
* @return a URL path without leading slash.
*/
public static String removeLeadingSlashes(String path) {
return SLASH_PREFIX_PATTERN.matcher(path).replaceFirst("");
}
/**
* Removes the trailing slashes of a URL path.
*
* @param path the URL path to be transformed.
* @return a URL path without leading slash.
*/
public static String removeTrailingSlashes(String path) {
return TRAILING_SLASH_PATTERN.matcher(path).replaceFirst("");
}
/**
* Encodes the given String using URL-encoding.
*
* @param raw the raw String to be encoded.
* @return the URL-encoded version of the provided String if it was valid UTF-8.
*/
public static Optional<String> urlEncode(String raw) {
try {
return Optional.of(URLEncoder.encode(raw, UTF_8.toString()));
} catch (UnsupportedEncodingException e) {
return Optional.empty();
}
}
private UrlUtils() {}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/db/ConnectionProvider.java
================================================
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/** A client library that communicates with different databases via jdbc. */
public class ConnectionProvider implements ConnectionProviderInterface {
public ConnectionProvider() {}
@Override
public Connection getConnection(String url, String user, String password) throws SQLException {
return DriverManager.getConnection(url, user, password);
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/db/ConnectionProviderInterface.java
================================================
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.db;
import java.sql.Connection;
import java.sql.SQLException;
/** A client interface that communicates with different databases. */
public interface ConnectionProviderInterface {
public Connection getConnection(String url, String user, String password) throws SQLException;
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpClient.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.tsunami.proto.NetworkService;
import java.io.IOException;
import java.time.Duration;
import org.checkerframework.checker.nullness.qual.Nullable;
/** A client library that communicates with remote servers via the HTTP protocol. */
public abstract class HttpClient {
public static final String TSUNAMI_USER_AGENT = "TsunamiSecurityScanner";
/**
* Gets log id.
*
* @return log id string.
*/
public abstract String getLogId();
/**
* NOTE: This is a temporary hack to workaround OkHttp's hardcoded URL canonicalization algorithm.
* We should rewrite the entire library using a more flexible backend.
*
* <p>Sends the given HTTP request as is, blocking until full response is received.
*
* @param httpRequest the HTTP request to be sent by this client.
* @return the response returned from the HTTP server.
* @throws IOException if an I/O error occurs during the HTTP request.
*/
public abstract HttpResponse sendAsIs(HttpRequest httpRequest) throws IOException;
/**
* Sends the given HTTP request using this client, blocking until full response is received.
*
* @param httpRequest the HTTP request to be sent by this client.
* @return the response returned from the HTTP server.
* @throws IOException if an I/O error occurs during the HTTP request.
*/
public abstract HttpResponse send(HttpRequest httpRequest) throws IOException;
/**
* Sends the given HTTP request using this client blocking until full response is received. If
* {@code networkService} is not null, the host header is set according to the service's header
* field even if it resolves to a different ip.
*
* @param httpRequest the HTTP request to be sent by this client.
* @param networkService the {@link NetworkService} proto to be used for the HOST header.
* @return the response returned from the HTTP server.
* @throws IOException if an I/O error occurs during the HTTP request.
*/
public abstract HttpResponse send(
HttpRequest httpRequest, @Nullable NetworkService networkService) throws IOException;
/**
* Sends the given HTTP request using this client asynchronously.
*
* @param httpRequest the HTTP request to be sent by this client.
* @return the future for the response to be returned from the HTTP server.
*/
public abstract ListenableFuture<HttpResponse> sendAsync(HttpRequest httpRequest);
/**
* Sends the given HTTP request using this client asynchronously. If {@code networkService} is not
* null, the host header is set according to the service's header field even if it resolves to a
* different ip.
*
* @param httpRequest the HTTP request to be sent by this client.
* @param networkService the {@link NetworkService} proto to be used for the HOST header.
* @return the future for the response to be returned from the HTTP server.
*/
public abstract ListenableFuture<HttpResponse> sendAsync(
HttpRequest httpRequest, @Nullable NetworkService networkService);
public abstract <T extends HttpClient> Builder<T> modify();
/** Base builder for implementations of HttpClient */
public abstract static class Builder<T extends HttpClient> {
public abstract Builder<T> setFollowRedirects(boolean followRedirects);
public abstract Builder<T> setLogId(String logId);
public abstract Builder<T> setConnectTimeout(Duration connectionTimeout);
public abstract T build();
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpClientCliOptions.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import com.google.tsunami.common.cli.CliOption;
import org.checkerframework.checker.nullness.qual.Nullable;
/** Command line argument for {@link HttpClient}. */
@Parameters(separators = "=")
public final class HttpClientCliOptions implements CliOption {
@Parameter(
names = "--http-client-trust-all-certificates",
arity = 1,
description = "Whether the HTTP client should trust all certificates on HTTPS traffic.")
public Boolean trustAllCertificates;
@Parameter(
names = "--http-client-call-timeout-seconds",
description =
"[Depreciated] Set to be the same as the timeout specified by"
+ " --http-client-connect-timeout-seconds.")
Integer callTimeoutSeconds;
@Parameter(
names = "--http-client-connect-timeout-seconds",
description =
"The timeout in seconds for new HTTP connections. See"
+ " https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/connect-timeout/"
+ " for more details.")
Integer connectTimeoutSeconds;
@Parameter(
names = "--http-client-read-timeout-seconds",
description =
"[Depreciated] Set to be the same as the timeout specified by"
+ " --http-client-connect-timeout-seconds")
Integer readTimeoutSeconds;
@Parameter(
names = "--http-client-write-timeout-seconds",
description =
"[Depreciated] Set to be the same as the timeout specified by"
+ " --http-client-connect-timeout-seconds.")
Integer writeTimeoutSeconds;
@Parameter(
names = "--http-client-user-agent",
description = "User-Agent to use in HTTP requests.")
public String userAgent = HttpClient.TSUNAMI_USER_AGENT;
@Override
public void validate() {
validateTimeout("--http-client-call-timeout-seconds", callTimeoutSeconds);
validateTimeout("--http-client-connect-timeout-seconds", connectTimeoutSeconds);
validateTimeout("--http-client-read-timeout-seconds", readTimeoutSeconds);
validateTimeout("--http-client-write-timeout-seconds", writeTimeoutSeconds);
}
private static void validateTimeout(String flagName, @Nullable Integer value) {
if (value != null && value < 0) {
throw new ParameterException(
String.format("%s cannot be a negative number, received %d.", flagName, value));
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpClientConfigProperties.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http;
import com.google.tsunami.common.config.annotations.ConfigProperties;
/** Configuration properties for {@link HttpClient}. */
@ConfigProperties("common.net.http")
public final class HttpClientConfigProperties {
/** Whether the HTTP client should trust all certificates on HTTPS traffic. */
Boolean trustAllCertificates;
/**
* The timeout in seconds for complete HTTP calls. See
* https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/call-timeout/ for
* more details.
*/
Integer callTimeoutSeconds;
/**
* The timeout in seconds for new HTTP connections. See
* https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/connect-timeout/
* for more details.
*/
Integer connectTimeoutSeconds;
/**
* The timeout in seconds for the read operations for HTTP connections. See
* https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/read-timeout/ for
* more details.
*/
Integer readTimeoutSeconds;
/**
* The timeout in seconds for the write operations for HTTP connections. See
* https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/write-timeout/ for
* more details.
*/
Integer writeTimeoutSeconds;
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpClientModule.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.tsunami.common.net.http.javanet.ConnectionFactory;
import com.google.tsunami.common.net.http.javanet.DefaultConnectionFactory;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.time.Duration;
import javax.inject.Qualifier;
import javax.inject.Singleton;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import okhttp3.OkHttpClient;
/** Guice module for installing {@link HttpClient} library. */
public final class HttpClientModule extends AbstractModule {
// This TrustManager does NOT validate certificate chains.
private static final X509TrustManager TRUST_ALL_CERTS_MANAGER =
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// Maximum number of requests for each host (URL's host name) to execute concurrently.
private static final int OKHTTPCLIENT_MAX_REQUESTS_PER_HOST = 5;
// Maximum number of idle connections to each to keep in the pool.
private final int connectionPoolMaxIdle;
// Duration to keep the connection alive in the pool before closing it.
private final Duration connectionPoolKeepAliveDuration;
// Maximum number of requests to execute concurrently.
private final int maxRequests;
// Whether or not to follow redirect from server.
private final boolean followRedirects;
// A log ID to print in front of the logs.
private final String logId;
public HttpClientModule(Builder builder) {
checkNotNull(builder);
this.connectionPoolMaxIdle = builder.connectionPoolMaxIdle;
this.connectionPoolKeepAliveDuration = builder.connectionPoolKeepAliveDuration;
this.maxRequests = builder.maxRequests;
this.followRedirects = builder.followRedirects;
this.logId = builder.logId;
}
@Provides
@Singleton
ConnectionPool provideConnectionPool() {
return new ConnectionPool(
connectionPoolMaxIdle, connectionPoolKeepAliveDuration.toMillis(), MILLISECONDS);
}
@Provides
@Singleton
Dispatcher provideDispatcher() {
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(maxRequests);
dispatcher.setMaxRequestsPerHost(OKHTTPCLIENT_MAX_REQUESTS_PER_HOST);
return dispatcher;
}
@Provides
@Singleton
@TrustAllCertsSocketFactory
SSLSocketFactory provideTrustAllCertsSocketFactory() throws GeneralSecurityException {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {TRUST_ALL_CERTS_MANAGER}, new SecureRandom());
return sslContext.getSocketFactory();
}
// Missing features:
// 1. Custom cookie handler.
@Provides
@Singleton
OkHttpClient provideOkHttpClient(
ConnectionPool connectionPool,
Dispatcher dispatcher,
@TrustAllCertsSocketFactory SSLSocketFactory trustAllCertsSocketFactory,
@TrustAllCertificates boolean trustAllCertificates,
@ConnectTimeoutSeconds int connectTimeoutSeconds) {
OkHttpClient.Builder clientBuilder =
new OkHttpClient.Builder()
.callTimeout(Duration.ofSeconds(connectTimeoutSeconds))
.connectTimeout(Duration.ofSeconds(connectTimeoutSeconds))
.readTimeout(Duration.ofSeconds(connectTimeoutSeconds))
.writeTimeout(Duration.ofSeconds(connectTimeoutSeconds))
.connectionPool(connectionPool)
.dispatcher(dispatcher)
.followRedirects(followRedirects);
if (trustAllCertificates) {
clientBuilder
.sslSocketFactory(trustAllCertsSocketFactory, TRUST_ALL_CERTS_MANAGER)
.hostnameVerifier((hostname, session) -> true);
}
return clientBuilder.build();
}
@Provides
@Singleton
HttpClient provideOkHttpHttpClient(
OkHttpClient okHttpClient,
@TrustAllCertificates boolean trustAllCertificates,
ConnectionFactory connectionFactory,
@LogId String logId,
@ConnectTimeout Duration connectTimeout,
@UserAgent String userAgent) {
return new OkHttpHttpClient(
okHttpClient, trustAllCertificates, connectionFactory, logId, connectTimeout, userAgent);
}
@Provides
@Singleton
ConnectionFactory provideJavaNetConnectionFactory(
@TrustAllCertificates boolean trustAllCertificates,
@TrustAllCertsSocketFactory SSLSocketFactory trustAllCertsSocketFactory,
@ConnectTimeoutSeconds int connectTimeoutSeconds,
@ReadTimeoutSeconds int readTimeoutSeconds) {
return new DefaultConnectionFactory(
trustAllCertificates,
trustAllCertsSocketFactory,
Duration.ofSeconds(connectTimeoutSeconds),
Duration.ofSeconds(readTimeoutSeconds));
}
@Provides
@TrustAllCertificates
boolean shouldTrustAllCertificates(
HttpClientCliOptions httpClientCliOptions,
HttpClientConfigProperties httpClientConfigProperties) {
if (httpClientCliOptions.trustAllCertificates != null) {
return httpClientCliOptions.trustAllCertificates;
}
if (httpClientConfigProperties.trustAllCertificates != null) {
return httpClientConfigProperties.trustAllCertificates;
}
return true;
}
@Provides
@LogId
String provideLogid() {
return logId;
}
@Provides
@FollowRedirects
boolean provideFollowRedirects() {
return followRedirects;
}
@Provides
@MaxRequests
int provideMaxRequests() {
return maxRequests;
}
@Provides
@CallTimeoutSeconds
int provideCallTimeoutSeconds(
HttpClientCliOptions httpClientCliOptions,
HttpClientConfigProperties httpClientConfigProperties) {
if (httpClientCliOptions.callTimeoutSeconds != null) {
return httpClientCliOptions.callTimeoutSeconds;
}
if (httpClientConfigProperties.callTimeoutSeconds != null) {
return httpClientConfigProperties.callTimeoutSeconds;
}
// Default call timeout specified in
// https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/call-timeout/.
return 0;
}
@Provides
@ConnectTimeoutSeconds
int provideConnectTimeoutSeconds(
HttpClientCliOptions httpClientCliOptions,
HttpClientConfigProperties httpClientConfigProperties) {
if (httpClientCliOptions.connectTimeoutSeconds != null) {
return httpClientCliOptions.connectTimeoutSeconds;
}
if (httpClientConfigProperties.connectTimeoutSeconds != null) {
return httpClientConfigProperties.connectTimeoutSeconds;
}
// Default connect timeout specified in
// https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/connect-timeout/.
return 10;
}
@Provides
@ConnectTimeout
Duration provideConnectTimeout(@ConnectTimeoutSeconds int connectionTimeoutSeconds) {
return Duration.ofSeconds(connectionTimeoutSeconds);
}
@Provides
@ReadTimeoutSeconds
int provideReadTimeoutSeconds(
HttpClientCliOptions httpClientCliOptions,
HttpClientConfigProperties httpClientConfigProperties) {
if (httpClientCliOptions.readTimeoutSeconds != null) {
return httpClientCliOptions.readTimeoutSeconds;
}
if (httpClientConfigProperties.readTimeoutSeconds != null) {
return httpClientConfigProperties.readTimeoutSeconds;
}
// Default read timeout specified in
// https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/read-timeout/.
return 10;
}
@Provides
@WriteTimeoutSeconds
int provideWriteTimeoutSeconds(
HttpClientCliOptions httpClientCliOptions,
HttpClientConfigProperties httpClientConfigProperties) {
if (httpClientCliOptions.writeTimeoutSeconds != null) {
return httpClientCliOptions.writeTimeoutSeconds;
}
if (httpClientConfigProperties.writeTimeoutSeconds != null) {
return httpClientConfigProperties.writeTimeoutSeconds;
}
// Default write timeout specified in
// https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/write-timeout/.
return 10;
}
@Provides
@UserAgent
String provideUserAgent(HttpClientCliOptions httpClientCliOptions) {
if (!isNullOrEmpty(httpClientCliOptions.userAgent)) {
return httpClientCliOptions.userAgent;
}
return HttpClient.TSUNAMI_USER_AGENT;
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface TrustAllCertificates {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface TrustAllCertsSocketFactory {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface LogId {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface CallTimeoutSeconds {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface ConnectTimeoutSeconds {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface ConnectTimeout {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface ReadTimeoutSeconds {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface WriteTimeoutSeconds {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface FollowRedirects {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface MaxRequests {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@interface UserAgent {}
/** Builder for {@link HttpClientModule}. */
public static final class Builder {
private static final int DEFAULT_CONNECTION_POOL_MAX_IDLE = 5;
private static final Duration DEFAULT_CONNECTION_POOL_KEEP_ALIVE_DURATION =
Duration.ofMinutes(5);
private static final int DEFAULT_MAX_REQUESTS = 64;
private static final boolean DEFAULT_FOLLOW_REDIRECTS = true;
private static final String DEFAULT_LOG_ID = "";
private int connectionPoolMaxIdle = DEFAULT_CONNECTION_POOL_MAX_IDLE;
private Duration connectionPoolKeepAliveDuration = DEFAULT_CONNECTION_POOL_KEEP_ALIVE_DURATION;
private int maxRequests = DEFAULT_MAX_REQUESTS;
private boolean followRedirects = DEFAULT_FOLLOW_REDIRECTS;
private String logId = DEFAULT_LOG_ID;
/**
* Sets the maximum number of idle connections to each to keep in the pool.
*
* @param maxIdle maximum number of idel connecteds.
* @return the {@link Builder} instance itself.
*/
public Builder setConnectionPoolMaxIdle(int maxIdle) {
checkArgument(maxIdle > 0);
this.connectionPoolMaxIdle = maxIdle;
return this;
}
/**
* Sets the duration to keep the connection alive in the connection pool before closing it.
*
* @param keepAliveDuration the duration to keep the connection alive.
* @return the {@link Builder} instance itself.
*/
public Builder setConnectionPoolKeepAliveDuration(Duration keepAliveDuration) {
checkNotNull(keepAliveDuration);
checkArgument(!keepAliveDuration.isNegative());
this.connectionPoolKeepAliveDuration = keepAliveDuration;
return this;
}
/**
* Sets the maximum number of requests to execute concurrently.
*
* @param maxRequests the maximum number of concurrent requests.
* @return the {@link Builder} instance itself.
*/
public Builder setMaxRequests(int maxRequests) {
checkArgument(maxRequests > 0);
this.maxRequests = maxRequests;
return this;
}
/**
* Sets whether or not to follow redirect from server. If unset, by default redirects will be
* followed.
*
* @param followRedirects whether the HTTP client should follow redirect responses from the
* server.
* @return the {@link Builder} instance itself.
*/
public Builder setFollowRedirects(boolean followRedirects) {
this.followRedirects = followRedirects;
return this;
}
/**
* Sets the log ID to print in front of the logs.
*
* @param logId the log ID to print in front of the logs.
* @return the {@link Builder} instance itself.
*/
public Builder setLogId(String logId) {
this.logId = logId;
return this;
}
public HttpClientModule build() {
return new HttpClientModule(this);
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpHeaders.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.auto.value.AutoValue;
import com.google.common.base.Ascii;
import com.google.common.base.CharMatcher;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.annotations.Immutable;
import java.lang.reflect.Field;
import java.util.Optional;
/** Immutable HTTP headers. */
@Immutable
@AutoValue
public abstract class HttpHeaders {
private static final ImmutableBiMap<String, String> LOWER_TO_KNOWN = createKnownHeaders();
private static final ImmutableSet<String> KNOWN = LOWER_TO_KNOWN.values();
/** Canonicalize a header name. */
private static String canonicalize(String headerName) {
if (KNOWN.contains(headerName)) {
return headerName;
}
String lower = Ascii.toLowerCase(headerName);
String known = LOWER_TO_KNOWN.get(lower);
return MoreObjects.firstNonNull(known, lower);
}
private static ImmutableBiMap<String, String> createKnownHeaders() {
ImmutableBiMap.Builder<String, String> builder = ImmutableBiMap.builder();
addFields(builder, com.google.common.net.HttpHeaders.class);
return builder.build();
}
/**
* Loops over all of the public String fields in the given class and puts them into the BiMap
* (lower case to original string value).
*/
private static void addFields(ImmutableBiMap.Builder<String, String> builder, Class<?> clazz) {
try {
for (Field field : clazz.getFields()) {
if (field.getType().equals(String.class)) {
String known = (String) field.get(null);
String lower = Ascii.toLowerCase(known);
builder.put(lower, known);
}
}
} catch (ReflectiveOperationException e) {
throw new IllegalStateException(e);
}
}
abstract ImmutableListMultimap<String, String> rawHeaders();
/**
* Gets a set of all HTTP header names.
*
* @return all HTTP header names.
*/
public ImmutableSet<String> names() {
return rawHeaders().keySet();
}
/**
* Returns the first value for the header with the given name, or empty Optional if none exists.
*
* @param name case-insensitive header name
* @return the first value for the given header name.
*/
public Optional<String> get(String name) {
checkNotNull(name, "Name cannot be null.");
ImmutableList<String> values = getAll(name);
return values.isEmpty() ? Optional.empty() : Optional.of(values.get(0));
}
/**
* Returns all the values for the header with the given name. Values are in the same order they
* were added to the builder.
*
* @param name case-insensitive header name
* @return All values for the given header name.
*/
public ImmutableList<String> getAll(String name) {
checkNotNull(name, "Name cannot be null.");
// We first check the multimap using whatever string is passed in. Usually
// this will be a constant from HttpHeaders, which is pre-canonicalized.
// Only if the lookup fails do we then canonicalize and try again.
ImmutableList<String> values = rawHeaders().get(name);
if (!values.isEmpty()) {
return values;
}
String fixedName = canonicalize(name);
if (fixedName.equals(name)) {
return values; // Name was already canonicalized, so return the empty list.
}
return rawHeaders().get(fixedName);
}
public static Builder builder() {
return new AutoValue_HttpHeaders.Builder();
}
/** Builder for {@link HttpHeaders}. */
@AutoValue.Builder
public abstract static class Builder {
/** RFC 2616 section 4.2. */
private static final CharMatcher HEADER_NAME_MATCHER =
CharMatcher.inRange('!', '~').and(CharMatcher.isNot(':'));
/** RFC 2616 section 4.2. */
private static final CharMatcher HEADER_VALUE_MATCHER =
CharMatcher.inRange((char) 0, (char) 31) // No control characters
.or(CharMatcher.is((char) 127)) // or DEL
.negate()
.or(CharMatcher.is('\t')); // except horizontal-tab
abstract ImmutableListMultimap.Builder<String, String> rawHeadersBuilder();
public Builder addHeader(String name, String value) {
checkNotNull(name, "Name cannot be null.");
checkNotNull(value, "Value cannot be null.");
checkArgument(isLegalHeaderName(name), "Illegal header name %s", name);
checkArgument(isLegalHeaderValue(value), "Illegal header value %s", value);
rawHeadersBuilder().put(canonicalize(name), value);
return this;
}
public Builder addHeader(String name, String value, boolean canonicalize) {
checkNotNull(name, "Name cannot be null.");
checkNotNull(value, "Value cannot be null.");
if (canonicalize) {
return addHeader(name, value);
} else {
rawHeadersBuilder().put(name, value);
return this;
}
}
public abstract HttpHeaders build();
private static boolean isLegalHeaderName(String str) {
return HEADER_NAME_MATCHER.matchesAllOf(str);
}
private static boolean isLegalHeaderValue(String value) {
return HEADER_VALUE_MATCHER.matchesAllOf(value);
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpMethod.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http;
/** Represents HTTP methods. */
public enum HttpMethod {
// Add more http methods here if necessary.
GET("GET"),
HEAD("HEAD"),
POST("POST"),
PUT("PUT"),
DELETE("DELETE");
private final String string;
HttpMethod(String string) {
this.string = string;
}
@Override
public String toString() {
return string;
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpRequest.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.auto.value.AutoValue;
import com.google.common.base.Strings;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.ByteString;
import java.util.Optional;
import okhttp3.HttpUrl;
/** Immutable HTTP request. */
@Immutable
@AutoValue
@AutoValue.CopyAnnotations
@SuppressWarnings("Immutable")
public abstract class HttpRequest {
public abstract HttpMethod method();
public abstract String url();
public abstract HttpHeaders headers();
public abstract Optional<ByteString> requestBody();
public abstract Builder toBuilder();
/**
* Creates a {@link Builder} object for configuring {@link HttpRequest}.
*
* @return a {@link Builder} instance for the {@link HttpRequest} object.
*/
public static Builder builder() {
return new AutoValue_HttpRequest.Builder();
}
/**
* Create a new HTTP GET request with the given {@code url}.
*
* @param url the url of the GET request.
* @return a {@link Builder} object for configuring {@link HttpRequest}.
*/
public static Builder get(String url) {
checkArgument(!Strings.isNullOrEmpty(url));
return builder().setMethod(HttpMethod.GET).setUrl(url);
}
/**
* Create a new HTTP GET request with the given {@code uri}.
*
* @param uri the url of the GET request.
* @return a {@link Builder} object for configuring {@link HttpRequest}.
*/
public static Builder get(HttpUrl uri) {
checkNotNull(uri);
return builder().setMethod(HttpMethod.GET).setUrl(uri);
}
/**
* Create a new HTTP HEAD request with the given {@code url}.
*
* @param url the url of the HEAD request.
* @return a {@link Builder} object for configuring {@link HttpRequest}.
*/
public static Builder head(String url) {
checkArgument(!Strings.isNullOrEmpty(url));
return builder().setMethod(HttpMethod.HEAD).setUrl(url);
}
/**
* Create a new HTTP HEAD request with the given {@code uri}.
*
* @param uri the url of the HEAD request.
* @return a {@link Builder} object for configuring {@link HttpRequest}.
*/
public static Builder head(HttpUrl uri) {
checkNotNull(uri);
return builder().setMethod(HttpMethod.HEAD).setUrl(uri);
}
/**
* Create a new HTTP POST request with the given {@code url}.
*
* @param url the url of the POST request.
* @return a {@link Builder} object for configuring {@link HttpRequest}.
*/
public static Builder post(String url) {
checkArgument(!Strings.isNullOrEmpty(url));
return builder().setMethod(HttpMethod.POST).setUrl(url);
}
/**
* Create a new HTTP POST request with the given {@code uri}.
*
* @param uri the url of the POST request.
* @return a {@link Builder} object for configuring {@link HttpRequest}.
*/
public static Builder post(HttpUrl uri) {
checkNotNull(uri);
return builder().setMethod(HttpMethod.POST).setUrl(uri);
}
/**
* Create a new HTTP PUT request with the given {@code url}.
*
* @param url the url of the PUT request.
* @return a {@link Builder} object for configuring {@link HttpRequest}.
*/
public static Builder put(String url) {
checkArgument(!Strings.isNullOrEmpty(url));
return put(HttpUrl.parse(url));
}
/**
* Create a new HTTP PUT request with the given {@code uri}.
*
* @param uri the url of the PUT request.
* @return a {@link Builder} object for configuring {@link HttpRequest}.
*/
public static Builder put(HttpUrl uri) {
checkNotNull(uri);
return builder().setMethod(HttpMethod.PUT).setUrl(uri);
}
/**
* Create a new HTTP DELETE request with the given {@code url}.
*
* @param url the url of the DELETE request.
* @return a {@link Builder} object for configuring {@link HttpRequest}.
*/
public static Builder delete(String url) {
checkArgument(!Strings.isNullOrEmpty(url));
return builder().setMethod(HttpMethod.DELETE).setUrl(url);
}
/**
* Create a new HTTP DELETE request with the given {@code uri}.
*
* @param uri the url of the DELETE request.
* @return a {@link Builder} object for configuring {@link HttpRequest}.
*/
public static Builder delete(HttpUrl uri) {
checkNotNull(uri);
return builder().setMethod(HttpMethod.DELETE).setUrl(uri);
}
/** Builder for {@link HttpRequest}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setMethod(HttpMethod method);
public abstract Builder setUrl(String url);
public Builder setUrl(HttpUrl url) {
setUrl(url.toString());
return this;
}
public abstract Builder setHeaders(HttpHeaders httpHeaders);
public abstract Builder setRequestBody(ByteString requestBody);
public abstract Builder setRequestBody(Optional<ByteString> requestBody);
public Builder withEmptyHeaders() {
setHeaders(HttpHeaders.builder().build());
return this;
}
abstract HttpRequest autoBuild();
public HttpRequest build() {
HttpRequest httpRequest = autoBuild();
switch (httpRequest.method()) {
case GET:
case HEAD:
checkState(
!httpRequest.requestBody().isPresent(),
"A request body is not allowed for HTTP GET/HEAD request");
break;
case POST:
case PUT:
case DELETE:
break;
}
return httpRequest;
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpResponse.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http;
import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
import com.google.errorprone.annotations.Immutable;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.google.protobuf.ByteString;
import java.util.Optional;
import okhttp3.HttpUrl;
/** Immutable HTTP response. */
@Immutable
@AutoValue
@AutoValue.CopyAnnotations
// HttpUrl is immutable even if not marked as such.
@SuppressWarnings("Immutable")
public abstract class HttpResponse {
public abstract HttpStatus status();
public abstract HttpHeaders headers();
public abstract Optional<ByteString> bodyBytes();
// The URL that produced this response.
// TODO(b/173574468): Provide the full redirection request not just the Url.
public abstract Optional<HttpUrl> responseUrl();
/**
* Gets the body of the HTTP response as a UTF-8 encoded String.
*
* @return HTTP response body as a Java {@link String}.
*/
@Memoized
public Optional<String> bodyString() {
return bodyBytes().map(ByteString::toStringUtf8);
}
/**
* Tries to parse the response body as json and returns the parsing result as {@link JsonElement}.
* If parsing failed, an empty optional is returned.
*
* @return HTTP response body as a Gson {@link JsonElement} object.
*/
@Memoized
public Optional<JsonElement> bodyJson() {
try {
return bodyString().map(JsonParser::parseString);
} catch (RuntimeException e) {
// Do best-effort parsing and ignore Json parsing errors
return Optional.empty();
}
}
/**
* Tries to determine if a given field in Json response is equal to a specific value. If parsing
* failed, {@link com.google.gson.JsonSyntaxException} or {@link IllegalStateException} will be
* thrown.
*
* @return boolean
*/
public boolean jsonFieldEqualsToValue(String fieldname, String value) {
Optional<JsonPrimitive> jsonPrimitive =
bodyJson()
.map(JsonElement::getAsJsonObject)
.map(object -> object.getAsJsonPrimitive(fieldname));
return jsonPrimitive.isPresent() && jsonPrimitive.get().getAsString().equals(value);
}
public static Builder builder() {
return new AutoValue_HttpResponse.Builder();
}
/** Builder for {@link HttpResponse}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setStatus(HttpStatus httpStatus);
public abstract Builder setHeaders(HttpHeaders httpHeaders);
public abstract Builder setBodyBytes(ByteString bodyBytes);
public abstract Builder setBodyBytes(Optional<ByteString> bodyBytes);
public abstract Builder setResponseUrl(HttpUrl url);
public abstract Builder setResponseUrl(Optional<HttpUrl> url);
public abstract HttpResponse build();
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpStatus.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import com.google.common.collect.ImmutableMap;
import java.util.Arrays;
import java.util.function.Function;
/**
* HTTP Status Codes defined in RFC 2616, RFC 6585, RFC 4918 and RFC 7538.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"
* target="_top">http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html</a>
* @see <a href="http://tools.ietf.org/html/rfc6585"
* target="_top">http://tools.ietf.org/html/rfc6585</a>
* @see <a href="https://tools.ietf.org/html/rfc4918"
* target="_top">https://tools.ietf.org/html/rfc4918</a>
* @see <a href="https://tools.ietf.org/html/rfc7538"
* target="_top">https://tools.ietf.org/html/rfc7538</a>
*/
public enum HttpStatus {
// Default
HTTP_STATUS_UNSPECIFIED(0, "Status Unspecified"),
// Informational 1xx
CONTINUE(100, "Continue"),
SWITCHING_PROTOCOLS(101, "Switching Protocols"),
// Successful 2xx
OK(200, "Ok"),
CREATED(201, "Created"),
ACCEPTED(202, "Accepted"),
NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information"),
NO_CONTENT(204, "No Content"),
RESET_CONTENT(205, "Reset Content"),
PARTIAL_CONTENT(206, "Partial Content"),
MULTI_STATUS(207, "Multi-Status"),
// Redirection 3xx
MULTIPLE_CHOICES(300, "Multiple Choices"),
MOVED_PERMANENTLY(301, "Moved Permanently"),
FOUND(302, "Found"),
SEE_OTHER(303, "See Other"),
NOT_MODIFIED(304, "Not Modified"),
USE_PROXY(305, "Use Proxy"),
TEMPORARY_REDIRECT(307, "Temporary Redirect"),
PERMANENT_REDIRECT(308, "Permanent Redirect"),
// Client Error 4xx
BAD_REQUEST(400, "Bad Request"),
UNAUTHORIZED(401, "Unauthorized"),
PAYMENT_REQUIRED(402, "Payment Required"),
FORBIDDEN(403, "Forbidden"),
NOT_FOUND(404, "Not Found"),
METHOD_NOT_ALLOWED(405, "Method Not Allowed"),
NOT_ACCEPTABLE(406, "Not Acceptable"),
PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required"),
REQUEST_TIMEOUT(408, "Request Timeout"),
CONFLICT(409, "Conflict"),
GONE(410, "Gone"),
LENGTH_REQUIRED(411, "Length Required"),
PRECONDITION_FAILED(412, "Precondition Failed"),
REQUEST_ENTITY_TOO_LARGE(413, "Request Entity Too Large"),
REQUEST_URI_TOO_LONG(414, "Request Uri Too Long"),
UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"),
REQUEST_RANGE_NOT_SATISFIABLE(416, "Request Range Not Satisfiable"),
EXPECTATION_FAILED(417, "Expectation Failed"),
UNPROCESSABLE_ENTITY(422, "Unprocessable Entity"),
LOCKED(423, "Locked"),
FAILED_DEPENDENCY(424, "Failed Dependency"),
PRECONDITION_REQUIRED(428, "Precondition Required"),
TOO_MANY_REQUESTS(429, "Too Many Requests"),
REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large"),
// Server Error 5xx
INTERNAL_SERVER_ERROR(500, "Internal Server Error"),
NOT_IMPLEMENTED(501, "Not Implemented"),
BAD_GATEWAY(502, "Bad Gateway"),
SERVICE_UNAVAILABLE(503, "Service Unavailable"),
GATEWAY_TIMEOUT(504, "Gateway Timeout"),
HTTP_VERSION_NOT_SUPPORTED(505, "Http Version Not Supported"),
INSUFFICIENT_STORAGE(507, "Insufficient Storage"),
NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required"),
/*
* IE returns this code for 204 due to its use of URLMon, which returns this
* code for 'Operation Aborted'. The status text is 'Unknown', the response
* headers are ''. Known to occur on IE 6 on XP through IE9 on Win7.
*/
QUIRK_IE_NO_CONTENT(1223, "Quirk IE No Content");
/** Status indexed by code. */
private static final ImmutableMap<Integer, HttpStatus> BY_CODE =
Arrays.stream(HttpStatus.values())
.collect(toImmutableMap(HttpStatus::code, Function.identity()));
/**
* Creates the {@link HttpStatus} from the given status code, or null if there is no known status
* with that code.
*
* @param code the HTTP status code.
* @return the matching {@link HttpStatus} from the given status code.
*/
public static HttpStatus fromCode(int code) {
HttpStatus status = BY_CODE.get(code);
return status == null ? HTTP_STATUS_UNSPECIFIED : status;
}
private final int code;
private final String name;
HttpStatus(int code, String name) {
this.code = code;
this.name = name;
}
public int code() {
return code;
}
public boolean isRedirect() {
switch (this) {
case MULTIPLE_CHOICES:
case MOVED_PERMANENTLY:
case FOUND:
case SEE_OTHER:
case TEMPORARY_REDIRECT:
case PERMANENT_REDIRECT:
return true;
default:
return false;
}
}
public boolean isSuccess() {
return code >= 200 && code < 300;
}
@Override
public String toString() {
return name;
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/OkHttpHttpClient.java
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.net.HttpHeaders.USER_AGENT;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.GoogleLogger;
import com.google.common.io.ByteSource;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.protobuf.ByteString;
import com.google.tsunami.common.net.http.javanet.ConnectionFactory;
import com.google.tsunami.proto.NetworkService;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Dns;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A client library that communicates with remote servers via the HTTP protocol using {@link
* OkHttpClient}.
*/
final class OkHttpHttpClient extends HttpClient {
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
private final OkHttpClient okHttpClient;
private final boolean trustAllCertificates;
private final ConnectionFactory connectionFactory;
private final String logId;
private final Duration connectionTimeout;
private final String userAgent;
OkHttpHttpClient(
OkHttpClient okHttpClient,
boolean trustAllCertificates,
ConnectionFactory connectionFactory,
String logId,
Duration connectionTimeout,
String userAgent) {
this.okHttpClient = checkNotNull(okHttpClient);
this.trustAllCertificates = trustAllCertificates;
this.connectionFactory = checkNotNull(connectionFactory);
this.logId = logId;
this.connectionTimeout = connectionTimeout;
this.userAgent = isNullOrEmpty(userAgent) ? TSUNAMI_USER_AGENT : userAgent;
}
/**
* Gets log id.
*
* @return log id string.
*/
@Override
public String getLogId() {
return this.logId;
}
/**
* NOTE: This is a temporary hack to workaround OkHttp's hardcoded URL canonicalization algorithm.
* We should rewrite the entire library using a more flexible backend.
*
* <p>Sends the given HTTP request as is, blocking until full response is received.
*
* @param httpRequest the HTTP request to be sent by this client.
* @return the response returned from the HTTP server.
* @throws IOException if an I/O error occurs during the HTTP request.
*/
@Override
public HttpResponse sendAsIs(HttpRequest httpRequest) throws IOException {
HttpURLConnection connection = connectionFactory.openConnection(httpRequest.url());
connection.setRequestMethod(httpRequest.method().toString());
httpRequest.headers().names().stream()
.filter(headerName -> !Ascii.equalsIgnoreCase(headerName, USER_AGENT))
.forEach(
headerName ->
httpRequest
.headers()
.getAll(headerName)
.forEach(
headerValue -> connection.setRequestProperty(headerName, headerValue)));
connection.setRequestProperty(USER_AGENT, this.userAgent);
if (ImmutableSet.of(HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE)
.contains(httpRequest.method())) {
connection.setDoOutput(true);
ByteSource.wrap(httpRequest.requestBody().orElse(ByteString.EMPTY).toByteArray())
.copyTo(connection.getOutputStream());
}
int responseCode = connection.getResponseCode();
HttpHeaders.Builder responseHeadersBuilder = HttpHeaders.builder();
for (Map.Entry<String, List<String>> headerEntry : connection.getHeaderFields().entrySet()) {
String headerName = headerEntry.getKey();
if (!isNullOrEmpty(headerName)) {
for (String headerValue : headerEntry.getValue()) {
if (!isNullOrEmpty(headerValue)) {
responseHeadersBuilder.addHeader(headerName, headerValue);
}
}
}
}
return HttpResponse.builder()
.setStatus(HttpStatus.fromCode(responseCode))
.setHeaders(responseHeadersBuilder.build())
.setBodyBytes(ByteString.readFrom(connection.getInputStream()))
.build();
}
/**
* Sends the given HTTP request using this client, blocking until full response is received.
*
* @param httpRequest the HTTP request to be sent by this client.
* @return the response returned from the HTTP server.
* @throws IOException if an I/O error occurs during the HTTP request.
*/
@Override
public HttpResponse send(HttpRequest httpRequest) throws IOException {
return send(httpRequest, null);
}
/**
* Sends the given HTTP request using this client blocking until full response is received. If
* {@code networkService} is not null, the host header is set according to the service's header
* field even if it resolves to a different ip.
*
* @param httpRequest the HTTP request to be sent by this client.
* @param networkService the {@link NetworkService} proto to be used for the HOST header.
* @return the response returned from the HTTP server.
* @throws IOException if an I/O error occurs during the HTTP request.
*/
@Override
public HttpResponse send(HttpRequest httpRequest, @Nullable NetworkService networkService)
throws IOException {
logger.atInfo().log(
"%sSending HTTP '%s' request to '%s'.", logId, httpRequest.method(), httpRequest.url());
OkHttpClient callHttpClient = clientWithHostnameAsProxy(networkService);
try (Response okHttpResponse =
callHttpClient.newCall(buildOkHttpRequest(httpRequest, this.userAgent)).execute()) {
return parseResponse(okHttpResponse);
}
}
/**
* Sends the given HTTP request using this client asynchronously.
*
* @param httpRequest the HTTP request to be sent by this client.
* @return the future for the response to be returned from the HTTP server.
*/
@Override
public ListenableFuture<HttpResponse> sendAsync(HttpRequest httpRequest) {
return sendAsync(httpRequest, null);
}
/**
* Sends the given HTTP request using this client asynchronously. If {@code networkService} is not
* null, the host header is set according to the service's header field even if it resolves to a
* different ip.
*
* @param httpRequest the HTTP request to be sent by this client.
* @param networkService the {@link NetworkService} proto to be used for the HOST header.
* @return the future for the response to be returned from the HTTP server.
*/
@Override
public ListenableFuture<HttpResponse> sendAsync(
HttpRequest httpRequest, @Nullable NetworkService networkService) {
logger.atInfo().log(
"%sSending async HTTP '%s' request to '%s'.",
logId, httpRequest.method(), httpRequest.url());
OkHttpClient callHttpClient = clientWithHostnameAsProxy(networkService);
SettableFuture<HttpResponse> responseFuture = SettableFuture.create();
Call requestCall = callHttpClient.newCall(buildOkHttpRequest(httpRequest, this.userAgent));
try {
requestCall.enqueue(
new Callback() {
@Override
public void onFailure(Call call, IOException e) {
responseFuture.setException(e);
}
@Override
public void onResponse(Call call, Response response) {
try (ResponseBody unused = response.body()) {
responseFuture.set(parseResponse(response));
} catch (Throwable t) {
responseFuture.setException(t);
}
}
});
} catch (Throwable t) {
responseFuture.setException(t);
}
// Makes sure cancellation state is propagated to OkHttp.
responseFuture.addListener(
() -> {
if (responseFuture.isCancelled()) {
requestCall.cancel();
}
},
directExecutor());
return responseFuture;
}
/*
* Returns a modified HTTP client that's configured to connect to the {@code networkService}'s IP
* and use its hostname in the host header, when both a hostname and an IP address is specified.
* Returns an unmodified HTTP client otherwise.
*/
private OkHttpClient clientWithHostnameAsProxy(NetworkService networkService) {
if (networkService == null) {
return this.okHttpClient;
}
String serviceIp = networkService.getNetworkEndpoint().getIpAddress().getAddress();
String serviceHostname = networkService.getNetworkEndpoint().getHostname().getName();
return this.okHttpClient
.newBuilder()
.dns(
hostname -> {
if (hostname.equals(serviceHostname)) {
hostname = serviceIp;
}
return Dns.SYSTEM.lookup(hostname);
})
.hostnameVerifier(
(hostname, session) -> {
if (trustAllCertificates) {
return true;
}
if (hostname.equals(serviceHostname)) {
return true;
}
return HttpsURLConnection.getDefaultHostnameVerifier().verify(hostname, session);
})
.build();
}
private static Request buildOkHttpRequest(HttpRequest httpRequest, String userAgent) {
Request.Builder okRequestBuilder = new Request.Builder().url(httpRequest.url());
httpRequest.headers().names().stream()
.filter(headerName -> !Ascii.equalsIgnoreCase(headerName, USER_AGENT))
.forEach(
headerName ->
httpRequest
.headers()
.getAll(headerName)
.forEach(headerValue -> okRequestBuilder.addHeader(headerName, headerValue)));
okRequestBuilder.addHeader(USER_AGENT, userAgent);
switch (httpRequest.method()) {
case GET:
okRequestBuilder.get();
break;
case HEAD:
okRequestBuilder.head();
break;
case PUT:
okRequestBuilder.put(buildRequestBody(httpRequest));
break;
case POST:
okRequestBuilder.post(buildRequestBody(httpRequest));
break;
case DELETE:
okRequestBuilder.delete(buildRequestBody(httpRequest));
break;
}
return okRequestBuilder.build();
}
private static RequestBody buildRequestBody(HttpRequest httpRequest) {
MediaType mediaType =
MediaType.parse(
httpRequest.headers().get(com.google.common.net.HttpHeaders.CONTENT_TYPE).orElse(""));
return RequestBody.create(
mediaType, httpRequest.requestBody().orElse(ByteString.EMPTY).toByteArray());
}
private static HttpResponse parseResponse(Response okResponse) throws IOException {
logger.atInfo().log(
"Received HTTP response with code '%d' for request to '%s'.",
okResponse.code(), okResponse.request().url());
HttpResponse.Builder httpResponseBuilder =
HttpResponse.builder()
.setStatus(HttpStatus.fromCode(okResponse.code()))
.setHeaders(convertHeaders(okResponse.headers()))
.setResponseUrl(okResponse.request().url());
if (!okResponse.request().method().equals(HttpMethod.HEAD.name())
&& okResponse.body() != null) {
httpResponseBuilder.setBodyBytes(ByteString.copyFrom(okResponse.body().bytes()));
}
return httpResponseBuilder.build();
}
private static HttpHeaders convertHeaders(Headers headers) {
HttpHeaders.Builder headersBuilder = HttpHeaders.builder();
for (int i = 0; i < headers.size(); i++) {
headersBuilder.addHeader(headers.name(i), headers.value(i));
}
return headersBuilder.build();
}
/**
* Returns a {@link Builder} that allows client code to modify the configurations of the internal
* http client.
*
* @return the {@link Builder} for modifying this client instance.
*/
@Override
@SuppressWarnings("unchecked") // safe covariant cast
public Builder<OkHttpHttpClient> modify() {
return new OkHttpHttpClientBuilder(this);
}
/** Builder for {@link OkHttpHttpClient}. */
// TODO(b/145315535): add more configurable options into the builder.
public static class OkHttpHttpClientBuilder extends Builder<OkHttpHttpClient> {
private final OkHttpClient okHttpClient;
private boolean followRedirects;
private boolean trustAllCertificates;
private final ConnectionFactory connectionFactory;
private String logId;
private Duration connectionTimeout;
private String userAgent;
private OkHttpHttpClientBuilder(OkHttpHttpClient okHttpHttpClient) {
this.okHttpClient = okHttpHttpClient.okHttpClient;
this.followRedirects = okHttpClient.followRedirects();
this.trustAllCertificates = okHttpHttpClient.trustAllCertificates;
this.connectionFactory = okHttpHttpClient.connectionFactory;
this.logId = okHttpHttpClient.logId;
this.connectionTimeout = okHttpHttpClient.connectionTimeout;
this.userAgent = okHttpHttpClient.userAgent;
}
@Override
public OkHttpHttpClientBuilder setFollowRedirects(boolean followRedirects) {
this.followRedirects = followRedirects;
return this;
}
@Override
public OkHttpHttpClientBuilder setLogId(String logId) {
this.logId = logId;
return this;
}
@Override
public OkHttpHttpClientBuilder setConnectTimeout(Duration connectionTimeout) {
this.connectionTimeout = connectionTimeout;
return this;
}
@CanIgnoreReturnValue
public OkHttpHttpClientBuilder setUserAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
@Override
public OkHttpHttpClient build() {
return new OkHttpHttpClient(
okHttpClient.newBuilder().followRedirects(followRedirects).build(),
trustAllCertificates,
connectionFactory,
logId,
connectionTimeout,
userAgent);
}
}
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/javanet/ConnectionFactory.java
================================================
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http.javanet;
import java.io.IOException;
import java.net.HttpURLConnection;
/** Given an URL, produces an {@link HttpURLConnection}. */
public interface ConnectionFactory {
/**
* Creates a new {@link HttpURLConnection} from the given {@code url}.
*
* @param url the URL to which the connection will be made
* @return the created connection object, which will still be in the pre-connected state
* @throws IOException if there was a problem producing the connection
*/
HttpURLConnection openConnection(String url) throws IOException;
}
================================================
FILE: common/src/main/java/com/google/tsunami/common/net/http/javanet/DefaultConnectionFactory.java
================================================
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.tsunami.common.net.http.javanet;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOExcept
gitextract_306kc4re/
├── .dockerignore
├── .gitattributes
├── .github/
│ └── workflows/
│ ├── core-build.yml
│ ├── core-push.yml
│ ├── devel-push.yml
│ └── full-push.yml
├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── common/
│ ├── README.md
│ ├── build.gradle
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── com/
│ │ └── google/
│ │ └── tsunami/
│ │ └── common/
│ │ ├── ErrorCode.java
│ │ ├── TsunamiException.java
│ │ ├── cli/
│ │ │ ├── CliOption.java
│ │ │ └── CliOptionsModule.java
│ │ ├── command/
│ │ │ ├── CommandExecutionThreadPool.java
│ │ │ ├── CommandExecutor.java
│ │ │ ├── CommandExecutorFactory.java
│ │ │ └── CommandExecutorModule.java
│ │ ├── concurrent/
│ │ │ ├── BaseThreadPoolModule.java
│ │ │ ├── ScheduledThreadPoolModule.java
│ │ │ └── ThreadPoolModule.java
│ │ ├── config/
│ │ │ ├── ConfigException.java
│ │ │ ├── ConfigLoader.java
│ │ │ ├── ConfigModule.java
│ │ │ ├── TsunamiConfig.java
│ │ │ ├── YamlConfigLoader.java
│ │ │ └── annotations/
│ │ │ └── ConfigProperties.java
│ │ ├── data/
│ │ │ ├── NetworkEndpointUtils.java
│ │ │ └── NetworkServiceUtils.java
│ │ ├── io/
│ │ │ └── archiving/
│ │ │ ├── Archiver.java
│ │ │ ├── GoogleCloudStorageArchiver.java
│ │ │ ├── GoogleCloudStorageArchiverModule.java
│ │ │ ├── RawFileArchiver.java
│ │ │ └── testing/
│ │ │ ├── FakeArchiver.java
│ │ │ ├── FakeGoogleCloudStorageArchivers.java
│ │ │ ├── FakeGoogleCloudStorageArchiversModule.java
│ │ │ ├── FakeRawFileArchiver.java
│ │ │ └── FakeRawFileArchiverModule.java
│ │ ├── net/
│ │ │ ├── FuzzingUtils.java
│ │ │ ├── UrlUtils.java
│ │ │ ├── db/
│ │ │ │ ├── ConnectionProvider.java
│ │ │ │ └── ConnectionProviderInterface.java
│ │ │ ├── http/
│ │ │ │ ├── HttpClient.java
│ │ │ │ ├── HttpClientCliOptions.java
│ │ │ │ ├── HttpClientConfigProperties.java
│ │ │ │ ├── HttpClientModule.java
│ │ │ │ ├── HttpHeaders.java
│ │ │ │ ├── HttpMethod.java
│ │ │ │ ├── HttpRequest.java
│ │ │ │ ├── HttpResponse.java
│ │ │ │ ├── HttpStatus.java
│ │ │ │ ├── OkHttpHttpClient.java
│ │ │ │ └── javanet/
│ │ │ │ ├── ConnectionFactory.java
│ │ │ │ └── DefaultConnectionFactory.java
│ │ │ └── socket/
│ │ │ ├── DefaultTsunamiSocketFactory.java
│ │ │ ├── TsunamiSocketFactory.java
│ │ │ ├── TsunamiSocketFactoryCliOptions.java
│ │ │ ├── TsunamiSocketFactoryConfigProperties.java
│ │ │ └── TsunamiSocketFactoryModule.java
│ │ ├── reflection/
│ │ │ ├── ClassGraphModule.java
│ │ │ └── RuntimeClassGraphScanResult.java
│ │ ├── server/
│ │ │ ├── CompactRunRequestHelper.java
│ │ │ └── LanguageServerCommand.java
│ │ ├── time/
│ │ │ ├── SystemUtcClockModule.java
│ │ │ ├── UtcClock.java
│ │ │ └── testing/
│ │ │ ├── FakeUtcClock.java
│ │ │ └── FakeUtcClockModule.java
│ │ └── version/
│ │ ├── ComparisonUtility.java
│ │ ├── KnownQualifier.java
│ │ ├── Segment.java
│ │ ├── Token.java
│ │ ├── Version.java
│ │ ├── VersionRange.java
│ │ └── VersionSet.java
│ └── test/
│ ├── java/
│ │ └── com/
│ │ └── google/
│ │ └── tsunami/
│ │ └── common/
│ │ ├── cli/
│ │ │ └── CliOptionsModuleTest.java
│ │ ├── command/
│ │ │ ├── CommandExecutorFactoryTest.java
│ │ │ └── CommandExecutorTest.java
│ │ ├── concurrent/
│ │ │ ├── BaseThreadPoolModuleTest.java
│ │ │ ├── ScheduledThreadPoolModuleTest.java
│ │ │ └── ThreadPoolModuleTest.java
│ │ ├── config/
│ │ │ ├── ConfigModuleTest.java
│ │ │ ├── TsunamiConfigTest.java
│ │ │ └── YamlConfigLoaderTest.java
│ │ ├── data/
│ │ │ ├── NetworkEndpointUtilsTest.java
│ │ │ └── NetworkServiceUtilsTest.java
│ │ ├── io/
│ │ │ └── archiving/
│ │ │ ├── ArchiverTestUtils.java
│ │ │ ├── GoogleCloudStorageArchiverTest.java
│ │ │ └── RawFileArchiverTest.java
│ │ ├── net/
│ │ │ ├── FuzzingUtilsTest.java
│ │ │ ├── UrlUtilsTest.java
│ │ │ ├── http/
│ │ │ │ ├── HttpClientModuleTest.java
│ │ │ │ ├── HttpHeadersTest.java
│ │ │ │ ├── HttpRequestTest.java
│ │ │ │ ├── HttpResponseTest.java
│ │ │ │ └── OkHttpHttpClientTest.java
│ │ │ └── socket/
│ │ │ ├── DefaultTsunamiSocketFactoryTest.java
│ │ │ ├── TsunamiSocketFactoryCliOptionsTest.java
│ │ │ └── TsunamiSocketFactoryModuleTest.java
│ │ ├── server/
│ │ │ └── CompactRunRequestHelperTest.java
│ │ ├── time/
│ │ │ ├── SystemUtcClockModuleTest.java
│ │ │ └── testing/
│ │ │ ├── FakeUtcClockModuleTest.java
│ │ │ └── FakeUtcClockTest.java
│ │ └── version/
│ │ ├── ComparisonUtilityTest.java
│ │ ├── EqualsTestCase.java
│ │ ├── KnownQualifierTest.java
│ │ ├── LessThanTestCase.java
│ │ ├── SegmentTest.java
│ │ ├── TokenTest.java
│ │ ├── VersionRangeTest.java
│ │ ├── VersionSetTest.java
│ │ └── VersionTest.java
│ └── resources/
│ └── com/
│ └── google/
│ └── tsunami/
│ └── common/
│ └── net/
│ └── http/
│ └── testdata/
│ ├── README.md
│ └── tsunami_test_server.p12
├── core.Dockerfile
├── devel.Dockerfile
├── docs/
│ ├── _config.yml
│ ├── _data/
│ │ └── nav.yml
│ ├── _includes/
│ │ └── nav.html
│ ├── _layouts/
│ │ ├── default.html
│ │ ├── home.html
│ │ └── post.html
│ ├── _posts/
│ │ ├── 2024-03-19-tsunami-network-scanner-ai-security.md
│ │ ├── 2025-06-18-changes-to-tsunami.md
│ │ └── 2025-10-16-october-update-tsunami-prp.md
│ ├── about/
│ │ └── index.md
│ ├── assets/
│ │ └── css/
│ │ └── style.scss
│ ├── blog/
│ │ └── index.html
│ ├── contribute/
│ │ ├── code-of-conduct.md
│ │ ├── contributing.md
│ │ └── index.md
│ ├── howto/
│ │ ├── common-patterns.md
│ │ ├── howto.md
│ │ ├── index.md
│ │ ├── new-detector/
│ │ │ ├── new-detector-java.md
│ │ │ └── templated/
│ │ │ ├── 00-getting-started.md
│ │ │ ├── 01-introduction.md
│ │ │ ├── 02-bootstrapping.md
│ │ │ ├── 03-first-actions.md
│ │ │ ├── 04-workflows.md
│ │ │ ├── 05-variables.md
│ │ │ ├── 06-callback-server.md
│ │ │ ├── 07-cleanup-actions.md
│ │ │ ├── 08-writing-unit-tests.md
│ │ │ ├── appendix-naming-actions.md
│ │ │ ├── appendix-naming-plugin.md
│ │ │ ├── appendix-naming-tests.md
│ │ │ ├── appendix-using-linter.md
│ │ │ ├── glossary-predefined-variables.md
│ │ │ └── glossary-tests-magic-uri.md
│ │ └── orchestration.md
│ └── index.md
├── full.Dockerfile
├── go.mod
├── main/
│ ├── README.md
│ ├── build.gradle
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── com/
│ │ └── google/
│ │ └── tsunami/
│ │ └── main/
│ │ └── cli/
│ │ ├── LanguageServerOptions.java
│ │ ├── ScanResultsArchiver.java
│ │ ├── ScanResultsArchiverModule.java
│ │ ├── TsunamiCli.java
│ │ ├── option/
│ │ │ ├── MainCliOptions.java
│ │ │ ├── OutputDataFormat.java
│ │ │ └── validator/
│ │ │ ├── IpV4Validator.java
│ │ │ ├── IpV6Validator.java
│ │ │ └── IpValidator.java
│ │ └── server/
│ │ ├── RemoteServerLoader.java
│ │ └── RemoteServerLoaderModule.java
│ └── test/
│ └── java/
│ └── com/
│ └── google/
│ └── tsunami/
│ └── main/
│ └── cli/
│ ├── LanguageServerOptionsTest.java
│ ├── ScanResultsArchiverTest.java
│ ├── TsunamiCliTest.java
│ ├── option/
│ │ ├── MainCliOptionsTest.java
│ │ ├── OutputDataFormatTest.java
│ │ └── validator/
│ │ ├── IpV4ValidatorTest.java
│ │ ├── IpV6ValidatorTest.java
│ │ └── IpValidatorTest.java
│ └── server/
│ └── RemoteServerLoaderTest.java
├── plugin/
│ ├── README.md
│ ├── build.gradle
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── google/
│ │ │ └── tsunami/
│ │ │ └── plugin/
│ │ │ ├── LanguageServerException.java
│ │ │ ├── PluginBootstrapModule.java
│ │ │ ├── PluginDefinition.java
│ │ │ ├── PluginExecutionException.java
│ │ │ ├── PluginExecutionModule.java
│ │ │ ├── PluginExecutionResult.java
│ │ │ ├── PluginExecutionThreadPool.java
│ │ │ ├── PluginExecutor.java
│ │ │ ├── PluginExecutorImpl.java
│ │ │ ├── PluginExecutorModule.java
│ │ │ ├── PluginLoadingModule.java
│ │ │ ├── PluginManager.java
│ │ │ ├── PluginManagerCliOptions.java
│ │ │ ├── PluginServiceClient.java
│ │ │ ├── PluginType.java
│ │ │ ├── PortScanner.java
│ │ │ ├── RemoteVulnDetector.java
│ │ │ ├── RemoteVulnDetectorImpl.java
│ │ │ ├── RemoteVulnDetectorLoadingModule.java
│ │ │ ├── ServiceFingerprinter.java
│ │ │ ├── TcsClient.java
│ │ │ ├── TcsClientCliOptions.java
│ │ │ ├── TcsConfigProperties.java
│ │ │ ├── TsunamiPlugin.java
│ │ │ ├── VulnDetector.java
│ │ │ ├── annotations/
│ │ │ │ ├── ForOperatingSystemClass.java
│ │ │ │ ├── ForServiceName.java
│ │ │ │ ├── ForSoftware.java
│ │ │ │ ├── ForWebService.java
│ │ │ │ ├── PluginInfo.java
│ │ │ │ └── RequiresCallbackServer.java
│ │ │ ├── payload/
│ │ │ │ ├── NotImplementedException.java
│ │ │ │ ├── Payload.java
│ │ │ │ ├── PayloadGenerator.java
│ │ │ │ ├── PayloadGeneratorModule.java
│ │ │ │ ├── PayloadSecretGenerator.java
│ │ │ │ ├── README.md
│ │ │ │ ├── Validator.java
│ │ │ │ └── testing/
│ │ │ │ ├── FakePayloadGeneratorModule.java
│ │ │ │ └── PayloadTestHelper.java
│ │ │ └── testing/
│ │ │ ├── FailedPortScanner.java
│ │ │ ├── FailedPortScannerBootstrapModule.java
│ │ │ ├── FailedRemoteVulnDetector.java
│ │ │ ├── FailedRemoteVulnDetectorBootstrapModule.java
│ │ │ ├── FailedServiceFingerprinter.java
│ │ │ ├── FailedServiceFingerprinterBootstrapModule.java
│ │ │ ├── FailedVulnDetector.java
│ │ │ ├── FailedVulnDetectorBootstrapModule.java
│ │ │ ├── FakePluginExecutionModule.java
│ │ │ ├── FakePortScanner.java
│ │ │ ├── FakePortScanner2.java
│ │ │ ├── FakePortScannerBootstrapModule.java
│ │ │ ├── FakePortScannerBootstrapModule2.java
│ │ │ ├── FakePortScannerBootstrapModuleEmpty.java
│ │ │ ├── FakePortScannerEmpty.java
│ │ │ ├── FakeRemoteVulnDetector.java
│ │ │ ├── FakeRemoteVulnDetectorBootstrapModule.java
│ │ │ ├── FakeServiceFingerprinter.java
│ │ │ ├── FakeServiceFingerprinterBootstrapModule.java
│ │ │ ├── FakeVulnDetector.java
│ │ │ ├── FakeVulnDetector2.java
│ │ │ ├── FakeVulnDetectorBootstrapModule.java
│ │ │ ├── FakeVulnDetectorBootstrapModule2.java
│ │ │ ├── FakeVulnDetectorBootstrapModuleEmpty.java
│ │ │ └── FakeVulnDetectorEmpty.java
│ │ └── resources/
│ │ └── com/
│ │ └── google/
│ │ └── tsunami/
│ │ └── plugin/
│ │ └── payload/
│ │ └── payload_definitions.yaml
│ └── test/
│ └── java/
│ └── com/
│ └── google/
│ └── tsunami/
│ └── plugin/
│ ├── PluginDefinitionTest.java
│ ├── PluginExecutorImplTest.java
│ ├── PluginLoadingModuleTest.java
│ ├── PluginManagerTest.java
│ ├── PluginServiceClientTest.java
│ ├── RemoteVulnDetectorImplTest.java
│ ├── RemoteVulnDetectorLoadingModuleTest.java
│ ├── TcsClientTest.java
│ └── payload/
│ ├── PayloadGeneratorModuleTest.java
│ ├── PayloadGeneratorWithCallbackServerTest.java
│ ├── PayloadGeneratorWithoutCallbackServerTest.java
│ ├── PayloadSecretGeneratorTest.java
│ └── PayloadTest.java
├── plugin_server/
│ └── py/
│ ├── common/
│ │ ├── data/
│ │ │ ├── network_endpoint_utils.py
│ │ │ ├── network_endpoint_utils_test.py
│ │ │ ├── network_service_utils.py
│ │ │ └── network_service_utils_test.py
│ │ └── net/
│ │ └── http/
│ │ ├── host_resolver_http_adapter.py
│ │ ├── host_resolver_http_adapter_test.py
│ │ ├── http_client.py
│ │ ├── http_header_fields.py
│ │ ├── http_header_fields_test.py
│ │ ├── http_headers.py
│ │ ├── http_headers_test.py
│ │ ├── http_method.py
│ │ ├── http_request.py
│ │ ├── http_request_test.py
│ │ ├── http_response.py
│ │ ├── http_response_test.py
│ │ ├── http_status.py
│ │ ├── http_status_test.py
│ │ ├── requests_http_client.py
│ │ └── requests_http_client_test.py
│ ├── plugin/
│ │ ├── payload/
│ │ │ ├── payload.py
│ │ │ ├── payload_generator.py
│ │ │ ├── payload_generator_test.py
│ │ │ ├── payload_generator_test_helper.py
│ │ │ ├── payload_secret_generator.py
│ │ │ ├── payload_secret_generator_test.py
│ │ │ ├── payload_test.py
│ │ │ ├── payload_utility.py
│ │ │ ├── payload_utility_test.py
│ │ │ └── validator.py
│ │ ├── tcs_client.py
│ │ └── tcs_client_test.py
│ ├── plugin_server.py
│ ├── plugin_service.py
│ ├── plugin_service_test.py
│ ├── requirements.in
│ ├── requirements.txt
│ └── tsunami_plugin.py
├── proto/
│ ├── build.gradle
│ ├── detection.proto
│ ├── go/
│ │ ├── detection_go_proto/
│ │ │ └── detection.pb.go
│ │ ├── network_go_proto/
│ │ │ └── network.pb.go
│ │ ├── network_service_go_proto/
│ │ │ └── network_service.pb.go
│ │ ├── payload_generator_go_proto/
│ │ │ └── payload_generator.pb.go
│ │ ├── plugin_representation_go_proto/
│ │ │ └── plugin_representation.pb.go
│ │ ├── plugin_service_go_proto/
│ │ │ └── plugin_service.pb.go
│ │ ├── reconnaissance_go_proto/
│ │ │ └── reconnaissance.pb.go
│ │ ├── scan_results_go_proto/
│ │ │ └── scan_results.pb.go
│ │ ├── scan_target_go_proto/
│ │ │ └── scan_target.pb.go
│ │ ├── software_go_proto/
│ │ │ └── software.pb.go
│ │ ├── vulnerability_go_proto/
│ │ │ └── vulnerability.pb.go
│ │ └── web_crawl_go_proto/
│ │ └── web_crawl.pb.go
│ ├── network.proto
│ ├── network_service.proto
│ ├── payload_generator.proto
│ ├── plugin_representation.proto
│ ├── plugin_service.proto
│ ├── reconnaissance.proto
│ ├── scan_results.proto
│ ├── scan_target.proto
│ ├── software.proto
│ ├── tsunami_go_proto/
│ │ ├── detection.pb.go
│ │ ├── network.pb.go
│ │ ├── network_service.pb.go
│ │ ├── payload_generator.pb.go
│ │ ├── plugin_representation.pb.go
│ │ ├── plugin_service.pb.go
│ │ ├── reconnaissance.pb.go
│ │ ├── scan_results.pb.go
│ │ ├── scan_target.pb.go
│ │ ├── software.pb.go
│ │ ├── vulnerability.pb.go
│ │ └── web_crawl.pb.go
│ ├── vulnerability.proto
│ └── web_crawl.proto
├── settings.gradle
├── tsunami.yaml
├── tsunami_tcs.yaml
└── workflow/
├── README.md
├── build.gradle
└── src/
├── main/
│ └── java/
│ └── com/
│ └── google/
│ └── tsunami/
│ └── workflow/
│ ├── AdvisoriesWorkflow.java
│ ├── DefaultScanningWorkflow.java
│ ├── ExecutionStage.java
│ ├── ExecutionTracer.java
│ └── ScanningWorkflowException.java
└── test/
└── java/
└── com/
└── google/
└── tsunami/
└── workflow/
├── DefaultScanningWorkflowTest.java
└── ExecutionTracerTest.java
Showing preview only (340K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3673 symbols across 253 files)
FILE: common/src/main/java/com/google/tsunami/common/ErrorCode.java
type ErrorCode (line 19) | public enum ErrorCode {
FILE: common/src/main/java/com/google/tsunami/common/TsunamiException.java
class TsunamiException (line 23) | public class TsunamiException extends RuntimeException {
method TsunamiException (line 26) | public TsunamiException() {
method TsunamiException (line 30) | public TsunamiException(ErrorCode errorCode) {
method TsunamiException (line 34) | public TsunamiException(ErrorCode errorCode, String message) {
method TsunamiException (line 38) | public TsunamiException(ErrorCode errorCode, String message, Throwable...
method buildExceptionMessage (line 43) | private static String buildExceptionMessage(ErrorCode errorCode, Strin...
method getErrorCode (line 52) | public ErrorCode getErrorCode() {
FILE: common/src/main/java/com/google/tsunami/common/cli/CliOption.java
type CliOption (line 25) | public interface CliOption {
method validate (line 32) | void validate();
FILE: common/src/main/java/com/google/tsunami/common/cli/CliOptionsModule.java
class CliOptionsModule (line 36) | public final class CliOptionsModule extends AbstractModule {
method CliOptionsModule (line 44) | public CliOptionsModule(ScanResult scanResult, String programName, Str...
method configure (line 52) | @Override
method bindCliOption (line 78) | private <T> T bindCliOption(Class<T> cliOptionClass) {
FILE: common/src/main/java/com/google/tsunami/common/command/CommandExecutor.java
class CommandExecutor (line 39) | public class CommandExecutor {
method CommandExecutor (line 49) | public CommandExecutor(String... args) {
method execute (line 60) | @VisibleForTesting
method execute (line 81) | public Process execute(Executor executor)
method executeAsync (line 102) | public Process executeAsync() throws IOException, InterruptedException...
method executeWithNoStreamCollection (line 116) | public Process executeWithNoStreamCollection()
method getOutput (line 123) | @Nullable
method getError (line 128) | @Nullable
method collectStream (line 133) | private static String collectStream(InputStream stream) {
FILE: common/src/main/java/com/google/tsunami/common/command/CommandExecutorFactory.java
class CommandExecutorFactory (line 19) | public class CommandExecutorFactory {
method setInstance (line 29) | public static void setInstance(CommandExecutor executor) {
method create (line 39) | public static CommandExecutor create(String... args) {
method CommandExecutorFactory (line 46) | private CommandExecutorFactory() {}
FILE: common/src/main/java/com/google/tsunami/common/command/CommandExecutorModule.java
class CommandExecutorModule (line 22) | public class CommandExecutorModule extends AbstractModule {
method configure (line 24) | @Override
FILE: common/src/main/java/com/google/tsunami/common/concurrent/BaseThreadPoolModule.java
class BaseThreadPoolModule (line 51) | abstract class BaseThreadPoolModule<ExecutorServiceT extends ListeningEx...
method BaseThreadPoolModule (line 62) | BaseThreadPoolModule(BaseThreadPoolModuleBuilder<ExecutorServiceT, ?> ...
method configure (line 75) | @Override
method configureThreadPool (line 81) | abstract void configureThreadPool(Key<ExecutorServiceT> key);
class BaseThreadPoolProvider (line 84) | abstract class BaseThreadPoolProvider implements Provider<ExecutorServ...
method createThreadPool (line 85) | abstract ExecutorService createThreadPool(
method get (line 92) | @Override
class BaseThreadPoolModuleBuilder (line 106) | abstract static class BaseThreadPoolModuleBuilder<
method BaseThreadPoolModuleBuilder (line 120) | BaseThreadPoolModuleBuilder(Class<ExecutorServiceT> executorServiceT...
method self (line 124) | abstract BuilderImplT self();
method setName (line 133) | public BuilderImplT setName(String name) {
method setMaxSize (line 145) | BuilderImplT setMaxSize(int maxSize) {
method setCoreSize (line 157) | BuilderImplT setCoreSize(int coreSize) {
method setKeepAliveSeconds (line 170) | public BuilderImplT setKeepAliveSeconds(long keepAliveSeconds) {
method setDaemon (line 182) | public BuilderImplT setDaemon(boolean daemon) {
method setDelayedShutdown (line 196) | public BuilderImplT setDelayedShutdown(Duration shutdownDelay) {
method setPriority (line 207) | public BuilderImplT setPriority(int priority) {
method setAnnotation (line 218) | public BuilderImplT setAnnotation(Annotation annotation) {
method setAnnotation (line 229) | public BuilderImplT setAnnotation(Class<? extends Annotation> annota...
method setRejectedExecutionHandler (line 245) | public BuilderImplT setRejectedExecutionHandler(
method validateAll (line 251) | final void validateAll() {
method validate (line 264) | abstract void validate();
method build (line 266) | public final AbstractModule build() {
method newModule (line 271) | abstract AbstractModule newModule();
FILE: common/src/main/java/com/google/tsunami/common/concurrent/ScheduledThreadPoolModule.java
class ScheduledThreadPoolModule (line 34) | public final class ScheduledThreadPoolModule
method ScheduledThreadPoolModule (line 37) | ScheduledThreadPoolModule(Builder builder) {
method configureThreadPool (line 41) | @Override
class ScheduledThreadPoolProvider (line 47) | private final class ScheduledThreadPoolProvider extends BaseThreadPool...
method createThreadPool (line 49) | @Override
class Builder (line 71) | public static final class Builder
method Builder (line 74) | public Builder() {
method self (line 78) | @Override
method setSize (line 89) | public Builder setSize(int size) {
method validate (line 96) | @Override
method newModule (line 99) | @Override
FILE: common/src/main/java/com/google/tsunami/common/concurrent/ThreadPoolModule.java
class ThreadPoolModule (line 41) | public final class ThreadPoolModule extends BaseThreadPoolModule<Listeni...
method ThreadPoolModule (line 44) | private ThreadPoolModule(Builder builder) {
method configureThreadPool (line 50) | @Override
class ThreadPoolProvider (line 57) | private final class ThreadPoolProvider extends BaseThreadPoolProvider {
method createThreadPool (line 58) | @Override
class Builder (line 77) | public static final class Builder
method Builder (line 82) | public Builder() {
method self (line 86) | @Override
method setMaxSize (line 92) | @Override
method setCoreSize (line 98) | @Override
method setQueueCapacity (line 115) | public Builder setQueueCapacity(int queueCapacity) {
method setBlockingQueue (line 131) | public Builder setBlockingQueue(BlockingQueue<Runnable> blockingQueu...
method getBlockingQueue (line 136) | private BlockingQueue<Runnable> getBlockingQueue() {
method isBoundedQueue (line 145) | private boolean isBoundedQueue() {
method validate (line 150) | @Override
method newModule (line 164) | @Override
FILE: common/src/main/java/com/google/tsunami/common/config/ConfigException.java
class ConfigException (line 22) | public class ConfigException extends TsunamiException {
method ConfigException (line 23) | public ConfigException(String message) {
method ConfigException (line 27) | public ConfigException(String message, Throwable cause) {
FILE: common/src/main/java/com/google/tsunami/common/config/ConfigLoader.java
type ConfigLoader (line 19) | public interface ConfigLoader {
method loadConfig (line 26) | TsunamiConfig loadConfig();
FILE: common/src/main/java/com/google/tsunami/common/config/ConfigModule.java
class ConfigModule (line 33) | public final class ConfigModule extends AbstractModule {
method ConfigModule (line 41) | public ConfigModule(ScanResult scanResult, TsunamiConfig tsunamiConfig) {
method configure (line 46) | @Override
method bindConfigClass (line 60) | private <T> void bindConfigClass(String configPrefix, Class<T> configC...
method getConfigPrefix (line 65) | private static String getConfigPrefix(ClassInfo configClass) {
FILE: common/src/main/java/com/google/tsunami/common/config/TsunamiConfig.java
class TsunamiConfig (line 30) | public final class TsunamiConfig {
method TsunamiConfig (line 37) | private TsunamiConfig(ImmutableMap<String, Object> rawConfigData) {
method getRawConfigData (line 41) | public ImmutableMap<String, Object> getRawConfigData() {
method fromYamlData (line 45) | public static TsunamiConfig fromYamlData(Map<String, Object> yamlConfi...
method getSystemProperty (line 50) | public static Optional<String> getSystemProperty(String propertyName) {
method getSystemProperty (line 54) | public static String getSystemProperty(String propertyName, String def) {
method getConfig (line 71) | public <T> T getConfig(String configPrefix, Class<T> clazz) {
method readConfigValue (line 79) | @SuppressWarnings("unchecked") // We know Map key is always String fro...
method newConfigObject (line 104) | private static <T> T newConfigObject(Class<T> clazz, Map<String, Objec...
FILE: common/src/main/java/com/google/tsunami/common/config/YamlConfigLoader.java
class YamlConfigLoader (line 32) | public final class YamlConfigLoader implements ConfigLoader {
method loadConfig (line 36) | @Override
method configFileReader (line 43) | private static Reader configFileReader() {
FILE: common/src/main/java/com/google/tsunami/common/data/NetworkEndpointUtils.java
class NetworkEndpointUtils (line 36) | public final class NetworkEndpointUtils {
method NetworkEndpointUtils (line 39) | private NetworkEndpointUtils() {}
method hasIpAddress (line 41) | public static boolean hasIpAddress(NetworkEndpoint networkEndpoint) {
method hasHostname (line 48) | public static boolean hasHostname(NetworkEndpoint networkEndpoint) {
method hasPort (line 55) | public static boolean hasPort(NetworkEndpoint networkEndpoint) {
method isIpV6Endpoint (line 61) | public static boolean isIpV6Endpoint(NetworkEndpoint networkEndpoint) {
method toUriAuthority (line 83) | public static String toUriAuthority(NetworkEndpoint networkEndpoint) {
method toHostAndPort (line 87) | public static HostAndPort toHostAndPort(NetworkEndpoint networkEndpoin...
method forIp (line 117) | public static NetworkEndpoint forIp(String ipAddress) {
method forIpAndPort (line 136) | public static NetworkEndpoint forIpAndPort(String ipAddress, int port) {
method forHostname (line 156) | public static NetworkEndpoint forHostname(String hostname) {
method forIpAndHostname (line 173) | public static NetworkEndpoint forIpAndHostname(String ipAddress, Strin...
method forHostnameAndPort (line 187) | public static NetworkEndpoint forHostnameAndPort(String hostname, int ...
method forIpHostnameAndPort (line 209) | public static NetworkEndpoint forIpHostnameAndPort(String ipAddress, S...
method forNetworkEndpointAndPort (line 231) | public static NetworkEndpoint forNetworkEndpointAndPort(
method ipAddressFamily (line 268) | public static AddressFamily ipAddressFamily(String ipAddress) {
FILE: common/src/main/java/com/google/tsunami/common/data/NetworkServiceUtils.java
class NetworkServiceUtils (line 45) | public final class NetworkServiceUtils {
method NetworkServiceUtils (line 61) | private NetworkServiceUtils() {}
method isWebService (line 63) | public static boolean isWebService(Optional<String> serviceName) {
method isWebService (line 69) | public static boolean isWebService(NetworkService networkService) {
method isPlainHttp (line 77) | public static boolean isPlainHttp(NetworkService networkService) {
method getServiceName (line 96) | public static String getServiceName(NetworkService networkService) {
method getWebServiceName (line 103) | public static String getWebServiceName(NetworkService networkService) {
method buildUriNetworkService (line 112) | public static NetworkService buildUriNetworkService(String uriString) {
method buildUriNetworkEndPoint (line 133) | private static NetworkEndpoint buildUriNetworkEndPoint(URI uri) {
method buildWebApplicationRootUrl (line 173) | public static String buildWebApplicationRootUrl(NetworkService network...
method buildWebAppRootPath (line 189) | private static String buildWebAppRootPath(NetworkService networkServic...
method buildWebUriAuthority (line 200) | private static String buildWebUriAuthority(NetworkService networkServi...
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/Archiver.java
type Archiver (line 24) | public interface Archiver {
method archive (line 33) | @CanIgnoreReturnValue
method archive (line 46) | @CanIgnoreReturnValue
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/GoogleCloudStorageArchiver.java
class GoogleCloudStorageArchiver (line 37) | public class GoogleCloudStorageArchiver implements Archiver {
class Options (line 47) | @Parameters(separators = "=")
method validate (line 61) | @Override
method GoogleCloudStorageArchiver (line 65) | @Inject
method parseBlobInfo (line 71) | private static BlobInfo parseBlobInfo(String gcsUrl) {
method archive (line 80) | @Override
type Factory (line 112) | public interface Factory {
method create (line 113) | GoogleCloudStorageArchiver create(Storage storage);
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/GoogleCloudStorageArchiverModule.java
class GoogleCloudStorageArchiverModule (line 22) | public class GoogleCloudStorageArchiverModule extends AbstractModule {
method configure (line 24) | @Override
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/RawFileArchiver.java
class RawFileArchiver (line 28) | public class RawFileArchiver implements Archiver {
method archive (line 31) | @Override
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeArchiver.java
class FakeArchiver (line 28) | public final class FakeArchiver implements Archiver {
method archive (line 33) | @Override
method archive (line 43) | @Override
method failArchival (line 53) | public void failArchival() {
method getStoredByteArrays (line 57) | public byte[] getStoredByteArrays(String name) {
method getStoredCharSequence (line 64) | public CharSequence getStoredCharSequence(String name) {
method assertNoByteArraysStored (line 71) | public void assertNoByteArraysStored() {
method assertNoCharSequencesStored (line 75) | public void assertNoCharSequencesStored() {
method assertNoDataStored (line 79) | public void assertNoDataStored() {
method assertByteArraysStored (line 84) | public void assertByteArraysStored(Map<String, byte[]> expectedData) {
method assertByteArraysStoredForNames (line 88) | public void assertByteArraysStoredForNames(Set<String> expectedNames) {
method assertByteArraysStoredWithValues (line 92) | public void assertByteArraysStoredWithValues(Collection<byte[]> expect...
method assertCharSequencesStored (line 96) | public void assertCharSequencesStored(Map<String, CharSequence> expect...
method assertCharSequencesStoredForNames (line 100) | public void assertCharSequencesStoredForNames(Set<String> expectedName...
method assertCharSequencesStoredWithValues (line 104) | public void assertCharSequencesStoredWithValues(Collection<CharSequenc...
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeGoogleCloudStorageArchivers.java
class FakeGoogleCloudStorageArchivers (line 25) | public final class FakeGoogleCloudStorageArchivers {
method assertNoDataStored (line 28) | public void assertNoDataStored() {
method getStoredByteArrays (line 41) | public byte[] getStoredByteArrays(Storage storage, String gcsUrl) {
method getStoredCharSequence (line 55) | public CharSequence getStoredCharSequence(Storage storage, String gcsU...
class FakeGoogleCloudStorageArchiver (line 62) | final class FakeGoogleCloudStorageArchiver extends GoogleCloudStorageA...
method FakeGoogleCloudStorageArchiver (line 65) | private FakeGoogleCloudStorageArchiver(Storage storage) {
method archive (line 70) | @Override
method archive (line 77) | @Override
class FakeFactory (line 85) | final class FakeFactory implements GoogleCloudStorageArchiver.Factory {
method create (line 87) | @Override
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeGoogleCloudStorageArchiversModule.java
class FakeGoogleCloudStorageArchiversModule (line 24) | public final class FakeGoogleCloudStorageArchiversModule extends Abstrac...
method provideGoogleCloudStorageArchiverFactory (line 26) | @Provides
method provideFakeGoogleCloudStorageArchivers (line 33) | @Provides
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeRawFileArchiver.java
class FakeRawFileArchiver (line 21) | public final class FakeRawFileArchiver extends RawFileArchiver {
method archive (line 24) | @Override
method archive (line 29) | @Override
method getStoredByteArrays (line 34) | public byte[] getStoredByteArrays(String fileName) {
method getStoredCharSequence (line 38) | public CharSequence getStoredCharSequence(String fileName) {
method assertNoDataStored (line 42) | public void assertNoDataStored() {
FILE: common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeRawFileArchiverModule.java
class FakeRawFileArchiverModule (line 23) | public final class FakeRawFileArchiverModule extends AbstractModule {
method configure (line 25) | @Override
FILE: common/src/main/java/com/google/tsunami/common/net/FuzzingUtils.java
class FuzzingUtils (line 33) | public final class FuzzingUtils {
method fuzzGetParametersWithDefaultParameter (line 40) | public static ImmutableList<HttpRequest> fuzzGetParametersWithDefaultP...
method fuzzGetParametersExpectingPathValues (line 50) | public static ImmutableList<HttpRequest> fuzzGetParametersExpectingPat...
method fuzzGetParameters (line 60) | public static ImmutableList<HttpRequest> fuzzGetParameters(HttpRequest...
method fuzzGetParameters (line 64) | private static ImmutableList<HttpRequest> fuzzGetParameters(
method setFuzzedParams (line 86) | private static ImmutableList<HttpQueryParameter> setFuzzedParams(
method fuzzParamsWithExtendedPathPayloads (line 93) | private static void fuzzParamsWithExtendedPathPayloads(
method fuzzParams (line 124) | private static ImmutableSet<ImmutableList<HttpQueryParameter>> fuzzPar...
method parseQuery (line 142) | public static ImmutableList<HttpQueryParameter> parseQuery(String quer...
method assembleUrlWithQueries (line 160) | private static String assembleUrlWithQueries(
method assembleQueryParams (line 177) | private static String assembleQueryParams(ImmutableList<HttpQueryParam...
class HttpQueryParameter (line 184) | @AutoValue
method name (line 186) | public abstract String name();
method value (line 188) | public abstract String value();
method create (line 190) | public static HttpQueryParameter create(String name, String value) {
type FuzzingModifier (line 195) | enum FuzzingModifier {
method FuzzingUtils (line 199) | private FuzzingUtils() {}
FILE: common/src/main/java/com/google/tsunami/common/net/UrlUtils.java
class UrlUtils (line 32) | public final class UrlUtils {
method allSubPaths (line 51) | public static ImmutableSet<HttpUrl> allSubPaths(String url) {
method allSubPaths (line 69) | public static ImmutableSet<HttpUrl> allSubPaths(HttpUrl url) {
method removeLeadingSlashes (line 108) | public static String removeLeadingSlashes(String path) {
method removeTrailingSlashes (line 118) | public static String removeTrailingSlashes(String path) {
method urlEncode (line 128) | public static Optional<String> urlEncode(String raw) {
method UrlUtils (line 136) | private UrlUtils() {}
FILE: common/src/main/java/com/google/tsunami/common/net/db/ConnectionProvider.java
class ConnectionProvider (line 23) | public class ConnectionProvider implements ConnectionProviderInterface {
method ConnectionProvider (line 24) | public ConnectionProvider() {}
method getConnection (line 26) | @Override
FILE: common/src/main/java/com/google/tsunami/common/net/db/ConnectionProviderInterface.java
type ConnectionProviderInterface (line 22) | public interface ConnectionProviderInterface {
method getConnection (line 23) | public Connection getConnection(String url, String user, String passwo...
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpClient.java
class HttpClient (line 25) | public abstract class HttpClient {
method getLogId (line 33) | public abstract String getLogId();
method sendAsIs (line 45) | public abstract HttpResponse sendAsIs(HttpRequest httpRequest) throws ...
method send (line 54) | public abstract HttpResponse send(HttpRequest httpRequest) throws IOEx...
method send (line 66) | public abstract HttpResponse send(
method sendAsync (line 75) | public abstract ListenableFuture<HttpResponse> sendAsync(HttpRequest h...
method sendAsync (line 86) | public abstract ListenableFuture<HttpResponse> sendAsync(
method modify (line 89) | public abstract <T extends HttpClient> Builder<T> modify();
class Builder (line 92) | public abstract static class Builder<T extends HttpClient> {
method setFollowRedirects (line 94) | public abstract Builder<T> setFollowRedirects(boolean followRedirects);
method setLogId (line 96) | public abstract Builder<T> setLogId(String logId);
method setConnectTimeout (line 98) | public abstract Builder<T> setConnectTimeout(Duration connectionTime...
method build (line 100) | public abstract T build();
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpClientCliOptions.java
class HttpClientCliOptions (line 25) | @Parameters(separators = "=")
method validate (line 68) | @Override
method validateTimeout (line 76) | private static void validateTimeout(String flagName, @Nullable Integer...
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpClientConfigProperties.java
class HttpClientConfigProperties (line 21) | @ConfigProperties("common.net.http")
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpClientModule.java
class HttpClientModule (line 46) | public final class HttpClientModule extends AbstractModule {
method checkClientTrusted (line 50) | @Override
method checkServerTrusted (line 53) | @Override
method getAcceptedIssuers (line 56) | @Override
method HttpClientModule (line 75) | public HttpClientModule(Builder builder) {
method provideConnectionPool (line 84) | @Provides
method provideDispatcher (line 91) | @Provides
method provideTrustAllCertsSocketFactory (line 100) | @Provides
method provideOkHttpClient (line 111) | @Provides
method provideOkHttpHttpClient (line 136) | @Provides
method provideJavaNetConnectionFactory (line 149) | @Provides
method shouldTrustAllCertificates (line 163) | @Provides
method provideLogid (line 177) | @Provides
method provideFollowRedirects (line 183) | @Provides
method provideMaxRequests (line 189) | @Provides
method provideCallTimeoutSeconds (line 195) | @Provides
method provideConnectTimeoutSeconds (line 211) | @Provides
method provideConnectTimeout (line 227) | @Provides
method provideReadTimeoutSeconds (line 233) | @Provides
method provideWriteTimeoutSeconds (line 249) | @Provides
method provideUserAgent (line 265) | @Provides
class Builder (line 330) | public static final class Builder {
method setConnectionPoolMaxIdle (line 350) | public Builder setConnectionPoolMaxIdle(int maxIdle) {
method setConnectionPoolKeepAliveDuration (line 362) | public Builder setConnectionPoolKeepAliveDuration(Duration keepAlive...
method setMaxRequests (line 375) | public Builder setMaxRequests(int maxRequests) {
method setFollowRedirects (line 389) | public Builder setFollowRedirects(boolean followRedirects) {
method setLogId (line 400) | public Builder setLogId(String logId) {
method build (line 405) | public HttpClientModule build() {
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpHeaders.java
class HttpHeaders (line 34) | @Immutable
method canonicalize (line 41) | private static String canonicalize(String headerName) {
method createKnownHeaders (line 50) | private static ImmutableBiMap<String, String> createKnownHeaders() {
method addFields (line 60) | private static void addFields(ImmutableBiMap.Builder<String, String> b...
method rawHeaders (line 74) | abstract ImmutableListMultimap<String, String> rawHeaders();
method names (line 81) | public ImmutableSet<String> names() {
method get (line 91) | public Optional<String> get(String name) {
method getAll (line 105) | public ImmutableList<String> getAll(String name) {
method builder (line 122) | public static Builder builder() {
class Builder (line 127) | @AutoValue.Builder
method rawHeadersBuilder (line 139) | abstract ImmutableListMultimap.Builder<String, String> rawHeadersBui...
method addHeader (line 141) | public Builder addHeader(String name, String value) {
method addHeader (line 150) | public Builder addHeader(String name, String value, boolean canonica...
method build (line 161) | public abstract HttpHeaders build();
method isLegalHeaderName (line 163) | private static boolean isLegalHeaderName(String str) {
method isLegalHeaderValue (line 167) | private static boolean isLegalHeaderValue(String value) {
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpMethod.java
type HttpMethod (line 19) | public enum HttpMethod {
method HttpMethod (line 29) | HttpMethod(String string) {
method toString (line 33) | @Override
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpRequest.java
class HttpRequest (line 30) | @Immutable
method method (line 35) | public abstract HttpMethod method();
method url (line 36) | public abstract String url();
method headers (line 37) | public abstract HttpHeaders headers();
method requestBody (line 38) | public abstract Optional<ByteString> requestBody();
method toBuilder (line 40) | public abstract Builder toBuilder();
method builder (line 47) | public static Builder builder() {
method get (line 57) | public static Builder get(String url) {
method get (line 68) | public static Builder get(HttpUrl uri) {
method head (line 79) | public static Builder head(String url) {
method head (line 90) | public static Builder head(HttpUrl uri) {
method post (line 101) | public static Builder post(String url) {
method post (line 112) | public static Builder post(HttpUrl uri) {
method put (line 123) | public static Builder put(String url) {
method put (line 134) | public static Builder put(HttpUrl uri) {
method delete (line 145) | public static Builder delete(String url) {
method delete (line 156) | public static Builder delete(HttpUrl uri) {
class Builder (line 162) | @AutoValue.Builder
method setMethod (line 164) | public abstract Builder setMethod(HttpMethod method);
method setUrl (line 165) | public abstract Builder setUrl(String url);
method setUrl (line 166) | public Builder setUrl(HttpUrl url) {
method setHeaders (line 170) | public abstract Builder setHeaders(HttpHeaders httpHeaders);
method setRequestBody (line 171) | public abstract Builder setRequestBody(ByteString requestBody);
method setRequestBody (line 172) | public abstract Builder setRequestBody(Optional<ByteString> requestB...
method withEmptyHeaders (line 174) | public Builder withEmptyHeaders() {
method autoBuild (line 179) | abstract HttpRequest autoBuild();
method build (line 180) | public HttpRequest build() {
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpResponse.java
class HttpResponse (line 29) | @Immutable
method status (line 35) | public abstract HttpStatus status();
method headers (line 36) | public abstract HttpHeaders headers();
method bodyBytes (line 37) | public abstract Optional<ByteString> bodyBytes();
method responseUrl (line 40) | public abstract Optional<HttpUrl> responseUrl();
method bodyString (line 47) | @Memoized
method bodyJson (line 58) | @Memoized
method jsonFieldEqualsToValue (line 75) | public boolean jsonFieldEqualsToValue(String fieldname, String value) {
method builder (line 83) | public static Builder builder() {
class Builder (line 88) | @AutoValue.Builder
method setStatus (line 90) | public abstract Builder setStatus(HttpStatus httpStatus);
method setHeaders (line 91) | public abstract Builder setHeaders(HttpHeaders httpHeaders);
method setBodyBytes (line 92) | public abstract Builder setBodyBytes(ByteString bodyBytes);
method setBodyBytes (line 93) | public abstract Builder setBodyBytes(Optional<ByteString> bodyBytes);
method setResponseUrl (line 94) | public abstract Builder setResponseUrl(HttpUrl url);
method setResponseUrl (line 95) | public abstract Builder setResponseUrl(Optional<HttpUrl> url);
method build (line 97) | public abstract HttpResponse build();
FILE: common/src/main/java/com/google/tsunami/common/net/http/HttpStatus.java
type HttpStatus (line 36) | public enum HttpStatus {
method fromCode (line 119) | public static HttpStatus fromCode(int code) {
method HttpStatus (line 127) | HttpStatus(int code, String name) {
method code (line 132) | public int code() {
method isRedirect (line 136) | public boolean isRedirect() {
method isSuccess (line 150) | public boolean isSuccess() {
method toString (line 154) | @Override
FILE: common/src/main/java/com/google/tsunami/common/net/http/OkHttpHttpClient.java
class OkHttpHttpClient (line 55) | final class OkHttpHttpClient extends HttpClient {
method OkHttpHttpClient (line 65) | OkHttpHttpClient(
method getLogId (line 85) | @Override
method sendAsIs (line 100) | @Override
method send (line 148) | @Override
method send (line 163) | @Override
method sendAsync (line 182) | @Override
method sendAsync (line 196) | @Override
method clientWithHostnameAsProxy (line 243) | private OkHttpClient clientWithHostnameAsProxy(NetworkService networkS...
method buildOkHttpRequest (line 271) | private static Request buildOkHttpRequest(HttpRequest httpRequest, Str...
method buildRequestBody (line 305) | private static RequestBody buildRequestBody(HttpRequest httpRequest) {
method parseResponse (line 313) | private static HttpResponse parseResponse(Response okResponse) throws ...
method convertHeaders (line 330) | private static HttpHeaders convertHeaders(Headers headers) {
method modify (line 344) | @Override
class OkHttpHttpClientBuilder (line 352) | public static class OkHttpHttpClientBuilder extends Builder<OkHttpHttp...
method OkHttpHttpClientBuilder (line 361) | private OkHttpHttpClientBuilder(OkHttpHttpClient okHttpHttpClient) {
method setFollowRedirects (line 371) | @Override
method setLogId (line 377) | @Override
method setConnectTimeout (line 383) | @Override
method setUserAgent (line 389) | @CanIgnoreReturnValue
method build (line 395) | @Override
FILE: common/src/main/java/com/google/tsunami/common/net/http/javanet/ConnectionFactory.java
type ConnectionFactory (line 22) | public interface ConnectionFactory {
method openConnection (line 31) | HttpURLConnection openConnection(String url) throws IOException;
FILE: common/src/main/java/com/google/tsunami/common/net/http/javanet/DefaultConnectionFactory.java
class DefaultConnectionFactory (line 31) | public class DefaultConnectionFactory implements ConnectionFactory {
method DefaultConnectionFactory (line 37) | public DefaultConnectionFactory(
method openConnection (line 48) | @Override
FILE: common/src/main/java/com/google/tsunami/common/net/socket/DefaultTsunamiSocketFactory.java
class DefaultTsunamiSocketFactory (line 38) | public final class DefaultTsunamiSocketFactory implements TsunamiSocketF...
method DefaultTsunamiSocketFactory (line 54) | public DefaultTsunamiSocketFactory(
method createSocket (line 72) | @Override
method createSocket (line 77) | @Override
method createSocket (line 82) | @Override
method createSocket (line 99) | @Override
method createSocket (line 104) | @Override
method createSocket (line 109) | @Override
method createUnconnectedSocket (line 127) | @Override
method createSslSocket (line 135) | @Override
method createSslSocket (line 140) | @Override
method createSslSocket (line 145) | @Override
method createSslSocket (line 169) | @Override
method createSslSocket (line 174) | @Override
method createSslSocket (line 180) | @Override
method wrapWithSsl (line 207) | @Override
method getDefaultConnectTimeout (line 229) | @Override
method getDefaultReadTimeout (line 234) | @Override
method configureAndConnect (line 248) | private void configureAndConnect(
FILE: common/src/main/java/com/google/tsunami/common/net/socket/TsunamiSocketFactory.java
type TsunamiSocketFactory (line 52) | public interface TsunamiSocketFactory {
method createSocket (line 65) | Socket createSocket(String host, int port) throws IOException;
method createSocket (line 78) | Socket createSocket(String host, int port, Duration timeout) throws IO...
method createSocket (line 90) | Socket createSocket(String host, int port, Duration connectTimeout, Du...
method createSocket (line 101) | Socket createSocket(InetAddress address, int port) throws IOException;
method createSocket (line 114) | Socket createSocket(InetAddress address, int port, Duration timeout) t...
method createSocket (line 126) | Socket createSocket(InetAddress address, int port, Duration connectTim...
method createUnconnectedSocket (line 138) | Socket createUnconnectedSocket() throws IOException;
method createSslSocket (line 151) | SSLSocket createSslSocket(String host, int port) throws IOException;
method createSslSocket (line 164) | SSLSocket createSslSocket(String host, int port, Duration timeout) thr...
method createSslSocket (line 176) | SSLSocket createSslSocket(String host, int port, Duration connectTimeo...
method createSslSocket (line 187) | SSLSocket createSslSocket(InetAddress address, int port) throws IOExce...
method createSslSocket (line 200) | SSLSocket createSslSocket(InetAddress address, int port, Duration time...
method createSslSocket (line 212) | SSLSocket createSslSocket(
method wrapWithSsl (line 229) | SSLSocket wrapWithSsl(Socket socket, String host, int port, boolean au...
method getDefaultConnectTimeout (line 236) | Duration getDefaultConnectTimeout();
method getDefaultReadTimeout (line 243) | Duration getDefaultReadTimeout();
FILE: common/src/main/java/com/google/tsunami/common/net/socket/TsunamiSocketFactoryCliOptions.java
class TsunamiSocketFactoryCliOptions (line 30) | @Parameters(separators = "=")
method validate (line 66) | @Override
method validateTimeout (line 76) | private static void validateTimeout(String flagName, @Nullable Integer...
FILE: common/src/main/java/com/google/tsunami/common/net/socket/TsunamiSocketFactoryConfigProperties.java
class TsunamiSocketFactoryConfigProperties (line 36) | @ConfigProperties("common.net.socket")
FILE: common/src/main/java/com/google/tsunami/common/net/socket/TsunamiSocketFactoryModule.java
class TsunamiSocketFactoryModule (line 62) | public final class TsunamiSocketFactoryModule extends AbstractModule {
method checkClientTrusted (line 73) | @Override
method checkServerTrusted (line 76) | @Override
method getAcceptedIssuers (line 79) | @Override
method configure (line 85) | @Override
method provideTsunamiSocketFactory (line 90) | @Provides
method provideDisableTimeouts (line 118) | @Provides
method provideTrustAllCertificates (line 132) | @Provides
method provideConnectTimeoutSeconds (line 146) | @Provides
method provideReadTimeoutSeconds (line 160) | @Provides
FILE: common/src/main/java/com/google/tsunami/common/reflection/ClassGraphModule.java
class ClassGraphModule (line 24) | public final class ClassGraphModule extends AbstractModule {
method ClassGraphModule (line 27) | public ClassGraphModule(ScanResult scanResult) {
method configure (line 31) | @Override
FILE: common/src/main/java/com/google/tsunami/common/server/CompactRunRequestHelper.java
class CompactRunRequestHelper (line 30) | public final class CompactRunRequestHelper {
method CompactRunRequestHelper (line 32) | private CompactRunRequestHelper() {}
method compress (line 34) | public static RunCompactRequest compress(RunRequest runRequest) {
method uncompress (line 59) | public static RunRequest uncompress(RunCompactRequest runCompactReques...
FILE: common/src/main/java/com/google/tsunami/common/server/LanguageServerCommand.java
class LanguageServerCommand (line 23) | @AutoValue
method create (line 25) | public static LanguageServerCommand create(
method serverCommand (line 51) | public abstract String serverCommand();
method serverAddress (line 53) | public abstract String serverAddress();
method port (line 55) | public abstract String port();
method logId (line 57) | public abstract String logId();
method outputDir (line 59) | public abstract String outputDir();
method trustAllSslCert (line 61) | public abstract boolean trustAllSslCert();
method timeoutSeconds (line 63) | public abstract Duration timeoutSeconds();
method callbackAddress (line 65) | public abstract String callbackAddress();
method callbackPort (line 67) | public abstract int callbackPort();
method pollingUri (line 69) | public abstract String pollingUri();
method deadlineRunSeconds (line 71) | public abstract int deadlineRunSeconds();
FILE: common/src/main/java/com/google/tsunami/common/time/SystemUtcClockModule.java
class SystemUtcClockModule (line 22) | public class SystemUtcClockModule extends AbstractModule {
method configure (line 24) | @Override
FILE: common/src/main/java/com/google/tsunami/common/time/testing/FakeUtcClock.java
class FakeUtcClock (line 33) | public final class FakeUtcClock extends Clock {
method FakeUtcClock (line 37) | private FakeUtcClock(Instant now) {
method create (line 50) | public static FakeUtcClock create() {
method setNow (line 60) | public FakeUtcClock setNow(Instant now) {
method advance (line 74) | public FakeUtcClock advance(Duration increment) {
method instant (line 80) | @Override
method getZone (line 85) | @Override
method withZone (line 90) | @Override
method equals (line 95) | @Override
method hashCode (line 104) | @Override
method toString (line 109) | @Override
FILE: common/src/main/java/com/google/tsunami/common/time/testing/FakeUtcClockModule.java
class FakeUtcClockModule (line 25) | public class FakeUtcClockModule extends AbstractModule {
method FakeUtcClockModule (line 28) | public FakeUtcClockModule() {
method FakeUtcClockModule (line 32) | public FakeUtcClockModule(FakeUtcClock fakeUtcClock) {
method configure (line 36) | @Override
FILE: common/src/main/java/com/google/tsunami/common/version/ComparisonUtility.java
class ComparisonUtility (line 21) | final class ComparisonUtility {
method ComparisonUtility (line 23) | private ComparisonUtility() {}
method compareListWithFillValue (line 38) | static <T extends Comparable<? super T>> int compareListWithFillValue(
FILE: common/src/main/java/com/google/tsunami/common/version/KnownQualifier.java
type KnownQualifier (line 27) | enum KnownQualifier implements Comparable<KnownQualifier> {
method KnownQualifier (line 40) | KnownQualifier(String qualifierText) {
method getQualifierText (line 44) | String getQualifierText() {
method isKnownQualifier (line 48) | static boolean isKnownQualifier(String string) {
method fromText (line 54) | static KnownQualifier fromText(String string) {
FILE: common/src/main/java/com/google/tsunami/common/version/Segment.java
class Segment (line 35) | @AutoValue
method tokens (line 53) | abstract ImmutableList<Token> tokens();
method fromTokenList (line 55) | static Segment fromTokenList(ImmutableList<Token> tokens) {
method fromString (line 67) | static Segment fromString(String segmentString) {
method parseFromString (line 71) | private static Segment parseFromString(String segmentString) {
method compareTo (line 102) | @Override
FILE: common/src/main/java/com/google/tsunami/common/version/Token.java
class Token (line 28) | @Immutable
type Kind (line 34) | public enum Kind {
method getKind (line 39) | abstract Kind getKind();
method getNumeric (line 41) | abstract long getNumeric();
method fromNumeric (line 42) | static Token fromNumeric(long numeric) {
method isNumeric (line 45) | boolean isNumeric() {
method getText (line 49) | abstract String getText();
method fromText (line 50) | static Token fromText(String string) {
method isText (line 53) | boolean isText() {
method fromKnownQualifier (line 57) | static Token fromKnownQualifier(KnownQualifier knownQualifier) {
method isKnownQualifier (line 60) | boolean isKnownQualifier() {
method isEmptyToken (line 63) | boolean isEmptyToken() {
method compareTo (line 67) | @Override
FILE: common/src/main/java/com/google/tsunami/common/version/Version.java
class Version (line 58) | @AutoValue
type Type (line 73) | public enum Type {
method versionType (line 79) | abstract Type versionType();
method versionString (line 80) | public abstract String versionString();
method segments (line 82) | @Memoized
method builder (line 97) | public static Builder builder() {
method fromString (line 101) | public static Version fromString(String versionString) {
method maximum (line 125) | public static Version maximum() {
method isMaximum (line 129) | public boolean isMaximum() {
method minimum (line 133) | public static Version minimum() {
method isMinimum (line 137) | public boolean isMinimum() {
method compareTo (line 156) | @Override
method isLessThan (line 174) | public boolean isLessThan(Version version) {
class Builder (line 179) | @AutoValue.Builder
method setVersionType (line 181) | public abstract Builder setVersionType(Type value);
method setVersionString (line 182) | public abstract Builder setVersionString(String value);
method build (line 184) | public abstract Version build();
FILE: common/src/main/java/com/google/tsunami/common/version/VersionRange.java
class VersionRange (line 26) | @AutoValue
type Inclusiveness (line 30) | public enum Inclusiveness {
method minVersion (line 35) | public abstract Version minVersion();
method minVersionInclusiveness (line 36) | public abstract Inclusiveness minVersionInclusiveness();
method maxVersion (line 37) | public abstract Version maxVersion();
method maxVersionInclusiveness (line 38) | public abstract Inclusiveness maxVersionInclusiveness();
method builder (line 40) | public static Builder builder() {
class Builder (line 45) | @AutoValue.Builder
method setMinVersion (line 47) | public abstract Builder setMinVersion(Version value);
method setMinVersionInclusiveness (line 48) | public abstract Builder setMinVersionInclusiveness(Inclusiveness val...
method setMaxVersion (line 49) | public abstract Builder setMaxVersion(Version value);
method setMaxVersionInclusiveness (line 50) | public abstract Builder setMaxVersionInclusiveness(Inclusiveness val...
method build (line 52) | public abstract VersionRange build();
method parse (line 71) | public static VersionRange parse(String rangeString) {
method isValidVersionRange (line 115) | public static boolean isValidVersionRange(String rangeString) {
method validateRangeString (line 124) | private static void validateRangeString(String rangeString) {
FILE: common/src/main/java/com/google/tsunami/common/version/VersionSet.java
class VersionSet (line 27) | @AutoValue
method versions (line 30) | public abstract ImmutableList<Version> versions();
method versionRanges (line 31) | public abstract ImmutableList<VersionRange> versionRanges();
method builder (line 33) | public static Builder builder() {
class Builder (line 38) | @AutoValue.Builder
method versionsBuilder (line 40) | abstract ImmutableList.Builder<Version> versionsBuilder();
method addVersion (line 41) | public Builder addVersion(Version version) {
method versionRangesBuilder (line 46) | abstract ImmutableList.Builder<VersionRange> versionRangesBuilder();
method addVersionRange (line 47) | public Builder addVersionRange(VersionRange versionRange) {
method build (line 52) | public abstract VersionSet build();
method parse (line 55) | public static VersionSet parse(ImmutableList<String> versionAndRangesL...
method isDiscreteVersion (line 77) | private static boolean isDiscreteVersion(String versionOrRangeString) {
FILE: common/src/test/java/com/google/tsunami/common/cli/CliOptionsModuleTest.java
class CliOptionsModuleTest (line 35) | @RunWith(JUnit4.class)
method configure_whenValidArgs_parsesSuccessfully (line 37) | @Test
method configure_whenMissingRequiredArgs_throwsException (line 59) | @Test
method configure_whenInvalidArgs_throwsException (line 77) | @Test
method configure_whenUnknownArgs_throwsException (line 91) | @Test
method configure_whenCliOptionNoCorrectCtor_throwsException (line 106) | @Test
class TestOption (line 121) | @Parameters(separators = "=")
method validate (line 126) | @Override
class TestOptionWithRequiredParam (line 138) | @Parameters(separators = "=")
method validate (line 143) | @Override
class TestOptionWithoutNoArgumentCtor (line 147) | @Parameters(separators = "=")
method TestOptionWithoutNoArgumentCtor (line 151) | TestOptionWithoutNoArgumentCtor(String testOption) {
method validate (line 155) | @Override
FILE: common/src/test/java/com/google/tsunami/common/command/CommandExecutorFactoryTest.java
class CommandExecutorFactoryTest (line 26) | @RunWith(JUnit4.class)
method getInstance_whenNoPreviousInstanceIsProvided_createsNewProcessExecutor (line 29) | @Test
method getInstance_whenPreviousInstanceIsProvided_returnsProvidedInstance (line 35) | @Test
FILE: common/src/test/java/com/google/tsunami/common/command/CommandExecutorTest.java
class CommandExecutorTest (line 27) | @RunWith(JUnit4.class)
method execute_always_startsProcessAndReturnsProcessInstance (line 30) | @Test
method executeAsync_always_startsProcessAndReturnsProcessInstance (line 41) | @Test
method executeWithNoStreamCollection_always_startsProcessAndReturnsProcessInstance (line 52) | @Test
method getOutput_always_returnsExpect (line 63) | @Test
method getOutput_withMultipleGetOutputCalls_returnsExpect (line 74) | @Test
method getError_always_returnsExpect (line 86) | @Test
method getError_withMultipleGetOutputCalls_returnsExpect (line 97) | @Test
FILE: common/src/test/java/com/google/tsunami/common/concurrent/BaseThreadPoolModuleTest.java
class BaseThreadPoolModuleTest (line 31) | @RunWith(JUnit4.class)
class TestThreadPoolModule (line 39) | static final class TestThreadPoolModule extends BaseThreadPoolModule<L...
method TestThreadPoolModule (line 41) | TestThreadPoolModule(Builder builder) {
method configureThreadPool (line 45) | @Override
class Builder (line 48) | static final class Builder
method Builder (line 51) | Builder() {
method self (line 55) | @Override
method validate (line 60) | @Override
method newModule (line 63) | @Override
method build_whenNoName_throwsIllegalStateException (line 70) | @Test
method build_whenEmptyName_throwsIllegalArgumentException (line 75) | @Test
method build_whenNegativeCoreSize_throwsIllegalArgumentException (line 82) | @Test
method build_whenNegativeMaxSize_throwsIllegalArgumentException (line 89) | @Test
method build_whenNegativeKeepAliveSeconds_throwsIllegalArgumentException (line 96) | @Test
method build_whenCoreSizeLessThanMaxSize_throwsIllegalStateException (line 108) | @Test
method build_whenNoAnnotation_throwsIllegalStateException (line 121) | @Test
FILE: common/src/test/java/com/google/tsunami/common/concurrent/ScheduledThreadPoolModuleTest.java
class ScheduledThreadPoolModuleTest (line 33) | @RunWith(JUnit4.class)
method configure_always_bindsListeningScheduledExecutorService (line 41) | @Test
method configure_always_bindsSingleton (line 56) | @Test
FILE: common/src/test/java/com/google/tsunami/common/concurrent/ThreadPoolModuleTest.java
class ThreadPoolModuleTest (line 36) | @RunWith(JUnit4.class)
method configure_always_bindsListeningExecutorService (line 44) | @Test
method configure_always_bindsSingleton (line 61) | @Test
method build_whenNegativeQueueCapacity_throwsIllegalArgumentException (line 82) | @Test
method build_whenBothQueueCapacityAndBlockingQueueSet_throwsIllegalStateException (line 94) | @Test
method build_whenUnBoundedQueue_throwsIllegalStateException (line 106) | @Test
FILE: common/src/test/java/com/google/tsunami/common/config/ConfigModuleTest.java
class ConfigModuleTest (line 32) | @RunWith(JUnit4.class)
method configure_always_bindsGivenTsunamiConfigObject (line 35) | @Test
method configure_whenValidConfigData_bindsSuccessfully (line 51) | @Test
method configure_whenMissingMatchedConfigData_bindsObjectWithDefaultValue (line 68) | @Test
method configure_whenValidConfigDataWithPrefix_bindsSuccessfully (line 84) | @Test
method configure_whenInvalidConfigClass_throwsException (line 103) | @Test
class TestConfigWithoutPrefix (line 118) | @ConfigProperties("")
class TestConfigWithPrefix (line 123) | @ConfigProperties("test.prefix")
class InvalidConfig (line 128) | @ConfigProperties("")
method InvalidConfig (line 132) | InvalidConfig(String stringConfig) {
FILE: common/src/test/java/com/google/tsunami/common/config/TsunamiConfigTest.java
class TsunamiConfigTest (line 31) | @RunWith(JUnit4.class)
method tearDown (line 35) | @After
method fromYamlData_always_createTsunamiConfigFromMapData (line 40) | @Test
method fromYamlData_whenNullYamlData_createEmptyConfigData (line 47) | @Test
method getSystemProperty_whenPropertyExists_returnsPropertyValue (line 54) | @Test
method getSystemProperty_whenPropertyNotExists_returnsEmptyOptional (line 61) | @Test
method getSystemProperty_whenPropertyNotExistsWithDefaultValue_returnsDefaultValue (line 66) | @Test
method getConfig_whenValidConfigData_returnsBoundConfigObject (line 71) | @Test
method getConfig_whenValidConfigDataAndPrefix_returnsBoundConfigObject (line 82) | @Test
method getConfig_whenRequestedConfigNotExists_returnsObjectWithDefaultValue (line 97) | @Test
method getConfig_whenConfigHasComplicateDataStructure_returnsValidObject (line 112) | @Test
method getConfig_whenConfigDataUseLowerUnderscoreCase_returnsValidObject (line 128) | @Test
method getConfig_whenRequestedConfigHasInvalidType_throwsException (line 144) | @Test
method getConfig_whenUnassignableConfigValue_throwsException (line 154) | @Test
method getConfig_whenInvalidConfigObject_throwsException (line 164) | @Test
class SimpleConfig (line 172) | private static final class SimpleConfig {
class CollectionConfig (line 177) | private static final class CollectionConfig {
class InvalidConfig (line 182) | private static final class InvalidConfig {
method InvalidConfig (line 185) | InvalidConfig(String field) {
FILE: common/src/test/java/com/google/tsunami/common/config/YamlConfigLoaderTest.java
class YamlConfigLoaderTest (line 30) | @RunWith(JUnit4.class)
method tearDown (line 34) | @After
method loadConfig_whenValidYamlFile_loadsConfigFromFile (line 39) | @Test
method loadConfig_whenYamlFileNotFound_usesEmptyConfig (line 50) | @Test
FILE: common/src/test/java/com/google/tsunami/common/data/NetworkEndpointUtilsTest.java
class NetworkEndpointUtilsTest (line 33) | @RunWith(JUnit4.class)
method isIpV6Endpoint_withIpV4Endpoint_returnsFalse (line 36) | @Test
method isIpV6Endpoint_withIpV4AndPortEndpoint_returnsFalse (line 47) | @Test
method isIpV6Endpoint_withIpV6Endpoint_returnsFalse (line 59) | @Test
method isIpV6Endpoint_withIpV6AndPortEndpoint_returnsFalse (line 70) | @Test
method isIpV6Endpoint_withHostnameEndpoint_returnsFalse (line 82) | @Test
method isIpV6Endpoint_withHostnameAndPortEndpoint_returnsFalse (line 92) | @Test
method toUriString_withIpV4Endpoint_returnsIpAddress (line 103) | @Test
method toUriString_withIpV6Endpoint_returnsIpAddressWithBracket (line 114) | @Test
method toUriString_withIpV4AndPortEndpoint_returnsIpAddressAndPort (line 125) | @Test
method toUriString_withIpV6AndPortEndpoint_returnsIpAddressWithBracketAndPort (line 137) | @Test
method toUriString_withHostnameEndpoint_returnsHostname (line 149) | @Test
method toUriString_withHostnameAndPortEndpoint_returnsHostnameAndPort (line 159) | @Test
method toHostAndPort_withIpAddress_returnsHostWithIp (line 171) | @Test
method toHostAndPort_withIpAddressAndPort_returnsHostWithIpAndPort (line 183) | @Test
method toHostAndPort_withHostname_returnsHostWithHostname (line 196) | @Test
method toHostAndPort_withHostnameAndPort_returnsHostWithHostnameAndPort (line 207) | @Test
method forIp_withIpV4Address_returnsIpV4NetworkEndpoint (line 219) | @Test
method forIp_withIpV6Address_returnsIpV6NetworkEndpoint (line 232) | @Test
method forIpAndPort_withIpV4AddressAndPort_returnsIpV4AndPortNetworkEndpoint (line 245) | @Test
method forIpAndPort_withIpV6AddressAndPort_returnsIpV6AndPortNetworkEndpoint (line 259) | @Test
method forHostname_withHostname_returnsHostnameNetworkEndpoint (line 273) | @Test
method forHostnameAndPort_withHostnameAndPort_returnsHostnameAndPortNetworkEndpoint (line 283) | @Test
method forIpAndHostname_returnsIpAndHostnameNetworkEndpoint (line 294) | @Test
method forIpHostnameAndPort_returnsIpHostnameAndPortNetworkEndpoint (line 308) | @Test
method forNetworkEndpointAndPort_withIpEndpointAndPort_returnsIpAndPort (line 323) | @Test
method forNetworkEndpointAndPort_withHostnameEndpointAndPort_returnsHostnameAndPort (line 339) | @Test
method forIp_withInvalidIp_throwsIllegalArgumentException (line 352) | @Test
method forIpAndPort_withInvalidIp_throwsIllegalArgumentException (line 357) | @Test
method forIpAndPort_withInvalidPort_throwsIllegalArgumentException (line 363) | @Test
method forHostname_withIpAddress_throwsIllegalArgumentException (line 371) | @Test
method forHostnameAndPort_withIpAddress_throwsIllegalArgumentException (line 377) | @Test
method forHostnameAndPort_withInvalidPort_throwsIllegalArgumentException (line 387) | @Test
method forNetworkEndpointAndPort_withInvalidEndpointType_throwsIllegalArgumentException (line 396) | @Test
method forNetworkEndpointAndPort_withInvalidPort_throwsIllegalArgumentException (line 410) | @Test
FILE: common/src/test/java/com/google/tsunami/common/data/NetworkServiceUtilsTest.java
class NetworkServiceUtilsTest (line 41) | @RunWith(JUnit4.class)
method isWebService_whenHttpService_returnsTrue (line 44) | @Test
method isWebService_whenHttpAltService_returnsTrue (line 52) | @Test
method isWebService_whenHttpProxyService_returnsTrue (line 60) | @Test
method isWebService_whenHttpsService_returnsTrue (line 68) | @Test
method isWebService_whenRadanHttpService_returnsTrue (line 76) | @Test
method isWebService_whenSslHttpService_returnsTrue (line 84) | @Test
method isWebService_whenSslHttpsService_returnsTrue (line 92) | @Test
method isWebService_whenCapitalizedHttpService_ignoresCaseAndReturnsTrue (line 100) | @Test
method isWebService_whenHasAtLeastOneHttpMethod_returnsTrue (line 108) | @Test
method isWebService_whenNonWebService_returnsFalse (line 119) | @Test
method isPlainHttp_whenPlainHttpService_returnsTrue (line 127) | @Test
method isPlainHttp_whenHttpAltService_returnsTrue (line 135) | @Test
method isPlainHttp_whenHttpsService_returnsFalse (line 143) | @Test
method isPlainHttp_whenRadanHttpService_returnsTrue (line 151) | @Test
method isPlainHttp_whenNonWebService_returnsFalse (line 159) | @Test
method isPlainHttp_whenHttpServiceButHasSslVersions_returnsFalse (line 167) | @Test
method isPlainHttp_whenNonHttpServiceButHasSslVersions_returnsFalse (line 178) | @Test
method isPlainHttp_whenHttpServiceFromHttpMethodsWithoutSslVersions_returnsTrue (line 189) | @Test
method isPlainHttp_whenHttpServiceWithSslVersions_returnsFalse (line 200) | @Test
method getServiceName_whenNonWebService_returnsServiceName (line 211) | @Test
method getServiceName_whenWebServiceNoSoftware_returnsServiceName (line 222) | @Test
method getServiceName_whenWebServiceWithSoftware_returnsServiceName (line 233) | @Test
method getWebServiceName_whenWebServiceWithSoftware_returnsWebServiceName (line 245) | @Test
method getServiceName_whenWebServiceNoContext_returnsServiceName (line 261) | @Test
method buildWebApplicationRootUrl_whenHttpWithoutRoot_buildsExpectedUrl (line 273) | @Test
method buildWebApplicationRootUrl_whenHttpsWithoutRoot_buildsExpectedUrl (line 284) | @Test
method buildWebApplicationRootUrl_whenHttpWithRootPath_buildsUrlWithExpectedRoot (line 299) | @Test
method buildWebApplicationRootUrl_whenRootPathNoLeadingSlash_appendsLeadingSlash (line 314) | @Test
method buildWebApplicationRootUrl_whenHttpServiceOnPort80_removesTrailingPortFromUrl (line 329) | @Test
method buildWebApplicationRootUrl_whenHttpsServiceOnPort443_removesTrailingPortFromUrl (line 344) | @Test
method buildWebApplicationRootUrl_whenNotWebService_returnsHttpUrl (line 359) | @Test
method buildUriNetworkService_returnsNetworkService (line 370) | @Test
FILE: common/src/test/java/com/google/tsunami/common/io/archiving/ArchiverTestUtils.java
class ArchiverTestUtils (line 19) | final class ArchiverTestUtils {
method ArchiverTestUtils (line 20) | private ArchiverTestUtils() {}
method newPreFilledByteArray (line 23) | static byte[] newPreFilledByteArray(int size) {
method newPreFilledByteArray (line 28) | static byte[] newPreFilledByteArray(int offset, int size) {
FILE: common/src/test/java/com/google/tsunami/common/io/archiving/GoogleCloudStorageArchiverTest.java
class GoogleCloudStorageArchiverTest (line 49) | @RunWith(JUnit4.class)
method setUp (line 66) | @Before
method archive_withSmallSizeString_createsBlobInOneRequest (line 80) | @Test
method archive_withSmallSizeBlob_createsBlobInOneRequest (line 94) | @Test
method archive_withLargeSizeString_createsBlobWithWriter (line 108) | @Test
method archive_withLargeSizeBlob_createsBlobWithWriter (line 130) | @Test
method archive_withLargeSizeBlobAndWriteError_returnsFalse (line 152) | @Test
method archive_withInvalidGcsUrl_throwsIllegalArgumentException (line 166) | @Test
method buildGcsUrl (line 173) | private static final String buildGcsUrl(String bucketId, String object...
FILE: common/src/test/java/com/google/tsunami/common/io/archiving/RawFileArchiverTest.java
class RawFileArchiverTest (line 32) | @RunWith(JUnit4.class)
method archive_whenValidTargetFileAndByteArrayData_archivesGivenDataWithGivenName (line 36) | @Test
method archive_whenInvalidTargetFileAndByteArrayData_returnsFalse (line 48) | @Test
method archive_whenValidTargetFileAndCharSequenceData_archivesGivenDataWithGivenName (line 59) | @Test
method archive_whenInvalidTargetFileAndCharSequenceData_returnsFalse (line 71) | @Test
FILE: common/src/test/java/com/google/tsunami/common/net/FuzzingUtilsTest.java
class FuzzingUtilsTest (line 26) | @RunWith(JUnit4.class)
method fuzzGetParametersWithDefaultParameter_whenNoGetParameters_addsDefaultParameter (line 33) | @Test
method fuzzGetParametersWithDefaultParameter_whenGetParameters_doesNotAddDefaultParameter (line 44) | @Test
method fuzzGetParametersWithDefaultParameter_whenGetParameters_fuzzesAllParameters (line 55) | @Test
method fuzzGetParametersExpectingPathValues_whenGetParameterValueHasFileExtension_appendsFileExtensionToPayload (line 72) | @Test
method fuzzGetParametersExpectingPathValues_whenGetParameterValueHasPathPrefix_prefixesPayload (line 86) | @Test
method fuzzGetParametersExpectingPathValues_whenGetParameterValueHasPathPrefixAndFileExtension_prefixesPayloadAndAppendsFileExtension (line 99) | @Test
method fuzzGetParametersExpectingPathValues_whenGetParameterValueHasPathPrefixOrFileExtension_prefixesPayloadOrAppendsFileExtension (line 115) | @Test
method fuzzGetParameters_whenNoGetParameters_returnsEmptyList (line 131) | @Test
method fuzzGetParameters_whenGetParameters_fuzzesAllParameters (line 137) | @Test
FILE: common/src/test/java/com/google/tsunami/common/net/UrlUtilsTest.java
class UrlUtilsTest (line 30) | @RunWith(JUnit4.class)
method allSubPaths_whenInvalidUrl_returnsEmptyList (line 33) | @Test
method allSubPaths_whenNoSubPathNoTrailingSlash_returnsSingleUrl (line 38) | @Test
method allSubPaths_whenNoSubPathWithTrailingSlash_returnsSingleUrl (line 43) | @Test
method allSubPaths_whenValidQueryParamsAndFragments_removesParamsAndFragments (line 49) | @Test
method allSubPaths_whenSingleSubPathsNoTrailingSlash_returnsExpectedUrl (line 55) | @Test
method allSubPaths_whenSingleSubPathsWithTrailingSlash_returnsExpectedUrl (line 61) | @Test
method allSubPaths_whenMultipleSubPathsNoTrailingSlash_returnsExpectedUrl (line 67) | @Test
method allSubPaths_whenMultipleSubPathsWithTrailingSlash_returnsExpectedUrl (line 77) | @Test
method allSubPaths_whenMultipleSubPathsWithParamsAndFragments_returnsExpectedUrl (line 87) | @Test
method removeLeadingSlashes_whenNoLeadingSlashes_returnsOriginal (line 97) | @Test
method removeLeadingSlashes_whenSingleLeadingSlash_removesLeadingSlashes (line 102) | @Test
method removeLeadingSlashes_whenMultipleLeadingSlashes_removesLeadingSlashes (line 107) | @Test
method removeTrailingSlashes_whenNoTrailingSlashes_returnsOriginal (line 112) | @Test
method removeTrailingSlashes_whenSingleTrailingSlash_removesTrailingSlashes (line 117) | @Test
method removeTrailingSlashes_whenMultipleTrailingSlashes_removesTrailingSlashes (line 122) | @Test
method urlEncode_whenEmptyString_returnsOriginal (line 127) | @Test
method urlEncode_whenNothingToEncode_returnsOriginal (line 132) | @Test
method urlEncode_whenNotEncoded_returnsEncoded (line 140) | @Test
method urlEncode_whenAlreadyEncoded_encodesAgain (line 148) | @Test
method urlEncode_whenComplexEncoding_encodesCorrectly (line 154) | @Test
method urlEncode_whenUnicode_encodesOriginal (line 162) | @Test
FILE: common/src/test/java/com/google/tsunami/common/net/http/HttpClientModuleTest.java
class HttpClientModuleTest (line 45) | @RunWith(JUnit4.class)
method provideHttpClient_always_createsSingleton (line 53) | @Test
method setConnectionPoolMaxIdle_whenNonPositiveMaxIdle_throwsIllegalArgumentException (line 64) | @Test
method setConnectionPoolKeepAliveDuration_whenNegativeDuration_throwsIllegalArgumentException (line 72) | @Test
method setMaxRequests_whenPositiveRequests_setsValueToDispatcher (line 82) | @Test
method setMaxRequests_whenNonPositiveRequests_throwsIllegalArgumentException (line 90) | @Test
method setFollowRedirects_always_setsValueToClient (line 98) | @Test
method setTrustAllCertificates_whenFalseAndCertIsInvalid_throws (line 106) | @Test
method setTrustAllCertificates_whenBothCliAndConfigValuesAreSet_cliValueTakesPrecedence (line 126) | @Test
method setTrustAllCertificates_whenCliOptionEnabledAndCertIsInvalid_ignoresCertError (line 146) | @Test
method setTrustAllCertificates_whenConfigPropropertyEnabledAndCertIsInvalid_ignoresCertError (line 160) | @Test
method setConnectTimeoutSeconds_whenSpecifiedUsingCliOptions_setsValueFromCli (line 175) | @Test
method setConnectTimeoutSeconds_whenSpecifiedUsingConfigProperties_setsValueFromConfig (line 184) | @Test
method setConnectTimeoutSeconds_whenBothCliAndConfigAreSet_cliTakesPrecedence (line 194) | @Test
method setConnectTimeoutSeconds_whenBothCliAndConfigAreNotSet_setsDefaultValue (line 205) | @Test
method getTestingGuiceModuleWithConfigs (line 213) | private AbstractModule getTestingGuiceModuleWithConfigs() {
method startMockWebServerWithSsl (line 224) | private MockWebServer startMockWebServerWithSsl() throws GeneralSecuri...
method getTestingSslSocketFactory (line 232) | private SSLSocketFactory getTestingSslSocketFactory()
FILE: common/src/test/java/com/google/tsunami/common/net/http/HttpHeadersTest.java
class HttpHeadersTest (line 27) | @RunWith(JUnit4.class)
method builderAddHeader_always_putsInHeadersMap (line 30) | @Test
method builderAddHeader_withKnownHeader_canonicalizesHeaderName (line 37) | @Test
method builderAddHeader_whenEnableCanonicalization_canonicalizesHeaderName (line 48) | @Test
method builderAddHeader_whenDisableCanonicalization_addsHeaderNameAsIs (line 59) | @Test
method builderAddHeader_withNullName_throwsNullPointerException (line 70) | @Test
method builderAddHeader_withNullValue_throwsNullPointerException (line 76) | @Test
method builderAddHeader_withIllegalHeaderName_throwsIllegalArgumentException (line 82) | @Test
method builderAddHeader_withIllegalHeaderValue_throwsIllegalArgumentException (line 88) | @Test
method names_always_returnsAllHeaderNames (line 95) | @Test
method get_whenRequestedHeaderExists_returnsRequestedHeader (line 110) | @Test
method get_whenMultipleValuesExist_returnsFirstValue (line 121) | @Test
method get_whenRequestedHeaderDoesNotExist_returnsEmpty (line 133) | @Test
method get_withNullHeaderName_throwsNullPointerException (line 145) | @Test
method getAll_always_returnsAllRequestedValues (line 157) | @Test
method getAll_withKnownHeaderValue_canonicalizesRequestedHeader (line 170) | @Test
method getAll_whenRequestValueDoesNotExist_returnsEmptyList (line 183) | @Test
FILE: common/src/test/java/com/google/tsunami/common/net/http/HttpRequestTest.java
class HttpRequestTest (line 27) | @RunWith(JUnit4.class)
method get_always_buildsHttpGetRequest (line 30) | @Test
method head_always_buildsHttpHeadRequest (line 38) | @Test
method post_always_buildsHttpPostRequest (line 46) | @Test
method delete_always_buildsHttpDeleteRequest (line 54) | @Test
method build_whenGetRequestHasRequestBody_throwsIllegalStateException (line 62) | @Test
FILE: common/src/test/java/com/google/tsunami/common/net/http/HttpResponseTest.java
class HttpResponseTest (line 30) | @RunWith(JUnit4.class)
method bodyJson_whenValidResponseBody_returnsParsedJson (line 35) | @Test
method bodyJson_whenEmptyResponseBody_returnsEmptyOptional (line 57) | @Test
method bodyJson_whenNonJsonResponseBody_returnsEmptyOptional (line 69) | @Test
method bodyJson_whenEmptyBodyResponseBody_throwsJsonSyntaxException (line 82) | @Test
method jsonFieldEqualsToValue_whenEmptyJsonResponseBody_returnsFalse (line 96) | @Test
method jsonFieldEqualsToValue_whenNonJsonResponseBody_returnsEmptyOptional (line 109) | @Test
method jsonFieldEqualsToValue_whenJsonFieldContainsValue_returnsTrue (line 122) | @Test
method bodyJson_whenHttpStatusInvalid_parseSucceeds (line 135) | @Test
FILE: common/src/test/java/com/google/tsunami/common/net/http/OkHttpHttpClientTest.java
class OkHttpHttpClientTest (line 64) | @RunWith(JUnit4.class)
method setUp (line 72) | @Before
method tearDown (line 78) | @After
method sendAsIs_always_returnsExpectedHttpResponse (line 83) | @Test
method sendAsIs_withPostRequest_returnsExpectedHttpResponse (line 117) | @Test
method send_always_canonicalizesRequestUrl (line 152) | @Test
method send_whenGetRequest_returnsExpectedHttpResponse (line 172) | @Test
method sendAsync_whenGetRequest_returnsExpectedHttpResponse (line 201) | @Test
method send_whenHeadRequest_returnsHttpResponseWithoutBody (line 231) | @Test
method sendAsync_whenHeadRequest_returnsHttpResponseWithoutBody (line 260) | @Test
method send_whenPostRequest_returnsExpectedHttpResponse (line 290) | @Test
method sendAsync_whenPostRequest_returnsExpectedHttpResponse (line 326) | @Test
method send_whenPostRequestWithEmptyHeaders_returnsExpectedHttpResponse (line 365) | @Test
method sendAsync_whenPostRequestWithEmptyHeaders_returnsExpectedHttpResponse (line 395) | @Test
method send_whenFollowRedirect_returnsFinalHttpResponse (line 425) | @Test
method sendAsync_whenFollowRedirect_returnsFinalHttpResponse (line 457) | @Test
method send_whenNotFollowRedirect_returnsFinalHttpResponse (line 491) | @Test
method sendAsync_whenNotFollowRedirect_returnsFinalHttpResponse (line 528) | @Test
method send_whenNoUserAgentInRequest_setsCorrectUserAgentHeader (line 567) | @Test
method send_whenUserAgentSetInRequest_overridesUserAgentHeader (line 581) | @Test
method send_whenRequestFailed_throwsException (line 596) | @Test
method sendAsync_whenRequestFailed_returnsFutureWithException (line 603) | @Test
method send_whenHostnameAndIpInRequest_useHostnameAsProxy (line 612) | @Test
method send_whenInvalidCertificatesAreIgnored_getResponseWithoutException (line 636) | @Test
method send_whenInvalidCertificatesAreNotIgnored_throws (line 674) | @Test
method send_default_userAgent (line 713) | @Test
method send_overridden_userAgent (line 730) | @Test
method startMockWebServerWithSsl (line 764) | private MockWebServer startMockWebServerWithSsl(InetAddress serverAddr...
method getTestingSslSocketFactory (line 773) | private SSLSocketFactory getTestingSslSocketFactory()
class RedirectDispatcher (line 785) | static final class RedirectDispatcher extends Dispatcher {
method RedirectDispatcher (line 791) | RedirectDispatcher(String responseBody) {
method dispatch (line 795) | @Override
class UserAgentTestDispatcher (line 810) | static final class UserAgentTestDispatcher extends Dispatcher {
method dispatch (line 813) | @Override
class HostnameTestDispatcher (line 823) | static final class HostnameTestDispatcher extends Dispatcher {
method HostnameTestDispatcher (line 826) | HostnameTestDispatcher(String expectedHost) {
method dispatch (line 830) | @Override
class SendAsIsTestDispatcher (line 839) | static final class SendAsIsTestDispatcher extends Dispatcher {
method buildBody (line 842) | static String buildBody(String method, String requestBody) {
method dispatch (line 846) | @Override
FILE: common/src/test/java/com/google/tsunami/common/net/socket/DefaultTsunamiSocketFactoryTest.java
class DefaultTsunamiSocketFactoryTest (line 43) | @RunWith(JUnit4.class)
method setUp (line 55) | @Before
method constructor_withNullSocketFactory_throwsException (line 71) | @Test
method constructor_withNullSslSocketFactory_throwsException (line 80) | @Test
method constructor_withNegativeConnectTimeout_throwsException (line 89) | @Test
method constructor_withNegativeReadTimeout_throwsException (line 101) | @Test
method createSocket_withHostAndPort_setsTimeoutsAndConnects (line 113) | @Test
method createSocket_withCustomTimeouts_usesProvidedValues (line 131) | @Test
method createSocket_withInetAddress_setsTimeoutsAndConnects (line 145) | @Test
method createSocket_withInvalidPort_throwsException (line 163) | @Test
method createSocket_withNullHost_throwsException (line 176) | @Test
method createUnconnectedSocket_setsReadTimeout (line 182) | @Test
method createSslSocket_withHostAndPort_createsAndConfigures (line 190) | @Test
method createSslSocket_withCustomTimeouts_usesProvidedValues (line 204) | @Test
method createSslSocket_withInetAddress_createsAndConfigures (line 220) | @Test
method wrapWithSsl_wrapsExistingSocket (line 232) | @Test
method wrapWithSsl_withZeroOriginalTimeout_usesDefault (line 243) | @Test
method wrapWithSsl_withNullSocket_throwsException (line 252) | @Test
method wrapWithSsl_withInvalidPort_throwsException (line 259) | @Test
method getDefaultConnectTimeout_returnsConfiguredValue (line 266) | @Test
method getDefaultReadTimeout_returnsConfiguredValue (line 271) | @Test
FILE: common/src/test/java/com/google/tsunami/common/net/socket/TsunamiSocketFactoryCliOptionsTest.java
class TsunamiSocketFactoryCliOptionsTest (line 26) | @RunWith(JUnit4.class)
method validate_withNullValues_passes (line 29) | @Test
method validate_withPositiveConnectTimeout_passes (line 37) | @Test
method validate_withPositiveReadTimeout_passes (line 46) | @Test
method validate_withNegativeConnectTimeout_throwsException (line 55) | @Test
method validate_withNegativeReadTimeout_throwsException (line 63) | @Test
method validate_withZeroConnectTimeout_throwsException (line 71) | @Test
method validate_withZeroReadTimeout_throwsException (line 79) | @Test
method validate_withTrustAllCertificates_passes (line 87) | @Test
method validate_withAllValidOptions_passes (line 96) | @Test
FILE: common/src/test/java/com/google/tsunami/common/net/socket/TsunamiSocketFactoryModuleTest.java
class TsunamiSocketFactoryModuleTest (line 34) | @RunWith(JUnit4.class)
method setUp (line 40) | @Before
method provideTsunamiSocketFactory_returnsNonNullFactory (line 46) | @Test
method provideTsunamiSocketFactory_withDefaultConfig_usesDefaultTimeouts (line 56) | @Test
method provideConnectTimeoutSeconds_withCliOption_usesCliValue (line 66) | @Test
method provideConnectTimeoutSeconds_withConfigOnly_usesConfigValue (line 76) | @Test
method provideConnectTimeoutSeconds_withNoConfig_usesDefault (line 85) | @Test
method provideReadTimeoutSeconds_withCliOption_usesCliValue (line 92) | @Test
method provideReadTimeoutSeconds_withConfigOnly_usesConfigValue (line 102) | @Test
method provideReadTimeoutSeconds_withNoConfig_usesDefault (line 111) | @Test
method provideTrustAllCertificates_withCliOptionTrue_returnsTrue (line 118) | @Test
method provideTrustAllCertificates_withCliOptionFalse_returnsFalse (line 128) | @Test
method provideTrustAllCertificates_withConfigOnly_usesConfigValue (line 137) | @Test
method provideTrustAllCertificates_withNoConfig_usesDefaultTrue (line 146) | @Test
method provideTsunamiSocketFactory_withCustomConfig_usesCustomValues (line 153) | @Test
method getTestingModule (line 165) | private AbstractModule getTestingModule() {
FILE: common/src/test/java/com/google/tsunami/common/server/CompactRunRequestHelperTest.java
class CompactRunRequestHelperTest (line 35) | @RunWith(JUnit4.class)
method compressingRunRequest_isMoreCompact (line 38) | @Test
FILE: common/src/test/java/com/google/tsunami/common/time/SystemUtcClockModuleTest.java
class SystemUtcClockModuleTest (line 29) | @RunWith(JUnit4.class)
method configure_always_bindsClockToSystemUtc (line 32) | @Test
FILE: common/src/test/java/com/google/tsunami/common/time/testing/FakeUtcClockModuleTest.java
class FakeUtcClockModuleTest (line 31) | @RunWith(JUnit4.class)
method constructor_withNullFakeClock_throwsNullPointerException (line 34) | @Test
method configure_always_bindsToSameInstance (line 39) | @Test
FILE: common/src/test/java/com/google/tsunami/common/time/testing/FakeUtcClockTest.java
class FakeUtcClockTest (line 28) | @RunWith(JUnit4.class)
method setNow_always_setsClockToGivenInstant (line 33) | @Test
method setNow_whenCallWithNull_throwsNullPointerException (line 38) | @Test
method advance_always_advancesGivenDuration (line 43) | @Test
method advance_whenCalledWithNull_throwsNullPointerException (line 52) | @Test
FILE: common/src/test/java/com/google/tsunami/common/version/ComparisonUtilityTest.java
class ComparisonUtilityTest (line 26) | @RunWith(JUnit4.class)
method compareWithFillValue_bothEmptyListWithFillValueEqualToZero_returnsZero (line 29) | @Test
method compareWithFillValue_bothEmptyListWithPositiveFillValue_returnsZero (line 37) | @Test
method compareWithFillValue_bothEmptyListWithNegativeFilValue_returnsZero (line 45) | @Test
method compareWithFillValue_oneEmptyListAndSmallFillValue_returnsNegative (line 53) | @Test
method compareWithFillValue_oneEmptyListAndLargeFillValue_returnsPositive (line 61) | @Test
method compareWithFillValue_nonEmptyListSameSizeGreaterValue_returnsPositive (line 69) | @Test
method compareWithFillValue_nonEmptyListSameSizeEqualValue_returnsZero (line 77) | @Test
method compareWithFillValue_nonEmptyListSameSizeLessThanValue_returnsNegative (line 85) | @Test
method compareWithFillValue_nonEmptyListVariedSizeWithPositiveFillValue_returnsNegative (line 93) | @Test
method compareWithFillValue_nonEmptyListVariedSizeWithZeroFillValue_returnsPositive (line 101) | @Test
method compareWithFillValue_nonEmptyListVariedSizeWithZeroFillValue_returnsNegative (line 109) | @Test
method compareWithFillValue_nonEmptyListVariedSizeWithPositiveFillValue_returnsPositive (line 117) | @Test
FILE: common/src/test/java/com/google/tsunami/common/version/EqualsTestCase.java
class EqualsTestCase (line 21) | @Immutable(containerOf = "T")
method first (line 24) | abstract T first();
method second (line 25) | abstract T second();
method create (line 27) | static <T> EqualsTestCase<T> create(T first, T second) {
FILE: common/src/test/java/com/google/tsunami/common/version/KnownQualifierTest.java
class KnownQualifierTest (line 32) | @RunWith(Theories.class)
method validTextsForKnownQualifiers (line 35) | @DataPoints("ValidKnownQualifierText")
method compareTo_always_hasTheCorrectOrder (line 42) | @Test
method isKnownQualifier_validText_returnsTrue (line 59) | @Theory
method isKnownQualifier_invalidText_returnsFalse (line 65) | @Theory
method fromText_validText_returnsKnownQualifier (line 70) | @Theory
method fromText_invalidText_throwsIllegalArgumentException (line 76) | @Test
method fromText_invalidTextUsingComposedValidTokens_throwsIllegalArgumentException (line 81) | @Test
FILE: common/src/test/java/com/google/tsunami/common/version/LessThanTestCase.java
class LessThanTestCase (line 21) | @Immutable(containerOf = "T")
method smaller (line 24) | abstract T smaller();
method larger (line 25) | abstract T larger();
method create (line 27) | static <T> LessThanTestCase<T> create(T smaller, T larger) {
FILE: common/src/test/java/com/google/tsunami/common/version/SegmentTest.java
class SegmentTest (line 31) | @RunWith(Theories.class)
method fromTokenList_startsWithKnownQualifier_buildsFromInput (line 34) | @Test
method fromTokenList_noKnownQualifier_addsKnownQualifier (line 43) | @Test
method fromString_emptyString_returnsNullSegment (line 55) | @Test
method fromString_allExcludedTokens_returnsNullSegment (line 60) | @Test
method fromString_allEmptyTokens_returnsNullSegment (line 65) | @Test
method fromString_textAndNumeric_returnsSeparatedTextAndNumber (line 70) | @Test
method fromString_noKnownQualifier_addsKnownQualifier (line 86) | @Test
method fromString_startsWithKnownQualifier_parsesNumericAndTextTokens (line 96) | @Test
method equalTestCases (line 106) | @DataPoints("Equals")
method compareTo_equalTestCase_returnsZero (line 115) | @Theory
method lessThanTestCases (line 121) | @DataPoints("LessThan")
method compareTo_lessThanTestCase_hasCorrectSymmetryResult (line 146) | @Theory
FILE: common/src/test/java/com/google/tsunami/common/version/TokenTest.java
class TokenTest (line 29) | @RunWith(Theories.class)
method fromNumeric_always_returnsNumericToken (line 32) | @Test
method fromText_always_returnsTextToken (line 39) | @Test
method fromKnownQualifier_always_returnsTextToken (line 47) | @Test
method equalTestCases (line 55) | @DataPoints("Equal")
method isEqualTo_equalTestCase_returnsZero (line 68) | @Theory
method lessThanTestCases (line 74) | @DataPoints("LessThan")
method compareTo_lessThanTestCase_hasCorrectSymmetryResult (line 114) | @Theory
FILE: common/src/test/java/com/google/tsunami/common/version/VersionRangeTest.java
class VersionRangeTest (line 27) | @RunWith(JUnit4.class)
method parse_withNegativeInfinityRange_returnsCorrectVersionRange (line 30) | @Test
method parse_withPositiveInfinityRange_returnsCorrectVersionRange (line 44) | @Test
method parse_withRegularRange_returnsCorrectVersionRange (line 58) | @Test
method parse_withEmptyRangeString_throwsIllegalArgumentException (line 72) | @Test
method parse_withRangeNotStartingWithParenthesis_throwsIllegalArgumentException (line 79) | @Test
method parse_withRangeNotEndingWithParenthesis_throwsIllegalArgumentException (line 88) | @Test
method parse_withTooManyParenthesis_throwsIllegalArgumentException (line 97) | @Test
method parse_withTooManyCommas_throwsIllegalArgumentException (line 106) | @Test
method parse_withoutComma_throwsIllegalArgumentException (line 113) | @Test
method parse_withMinimalToMaximalRange_throwsIllegalArgumentException (line 120) | @Test
method parse_withTheSameRangeEnds_throwsIllegalArgumentException (line 127) | @Test
FILE: common/src/test/java/com/google/tsunami/common/version/VersionSetTest.java
class VersionSetTest (line 27) | @RunWith(JUnit4.class)
method parse_withValidVersionsAndVersionRanges_returnsParsedVersionSet (line 30) | @Test
method parse_withEmptyInputList_throwsIllegalArgumentException (line 42) | @Test
method parse_withInvalidVersion_throwsIllegalArgumentException (line 49) | @Test
FILE: common/src/test/java/com/google/tsunami/common/version/VersionTest.java
class VersionTest (line 30) | @RunWith(Theories.class)
method create_whenNormalVersionAndValueIsNull_throwsException (line 33) | @Test
method create_whnNormalVersionAndValueIsEmpty_throwsExceptionIfStringIsNull (line 38) | @Test
method create_whenNormalVersion_returnsTypeNormal (line 43) | @Test
method createMaximum_always_returnsTypeMaximum (line 50) | @Test
method createMaximum_always_returnsTypeMinimum (line 57) | @Test
method invalidVersionTestCases (line 64) | @DataPoints("InvalidVersion")
method fromString_invalidVersionString_throwsIllegalArgumentException (line 69) | @Theory
method fromString_validString_storesInputAsRawString (line 75) | @Test
method fromString_noEpoch_appendsZeroEpoch (line 80) | @Test
method fromString_withEpoch_epochIsParsed (line 86) | @Test
method fromString_withMultipleSegments_segmentsParsedCorrectly (line 92) | @Test
method equalsTestCases (line 101) | @DataPoints("Equals")
method compareTo_equalsTestCase_returnsZero (line 111) | @Theory
method lessThanTestCases (line 117) | @DataPoints("LessThan")
method compareTo_lessThanTestCase_hasCorrectSymmetryResult (line 229) | @Theory
FILE: main/src/main/java/com/google/tsunami/main/cli/LanguageServerOptions.java
class LanguageServerOptions (line 29) | @Parameters(separators = "=")
method validate (line 65) | @Override
FILE: main/src/main/java/com/google/tsunami/main/cli/ScanResultsArchiver.java
class ScanResultsArchiver (line 38) | class ScanResultsArchiver {
class Options (line 40) | @Parameters(separators = "=")
method validate (line 69) | @Override
method ScanResultsArchiver (line 84) | @Inject
method getGcsStorage (line 95) | Storage getGcsStorage() {
method archive (line 99) | void archive(ScanResults scanResults) throws InvalidProtocolBufferExce...
method archive (line 115) | private static void archive(
FILE: main/src/main/java/com/google/tsunami/main/cli/ScanResultsArchiverModule.java
class ScanResultsArchiverModule (line 21) | final class ScanResultsArchiverModule extends AbstractModule {
method configure (line 23) | @Override
FILE: main/src/main/java/com/google/tsunami/main/cli/TsunamiCli.java
class TsunamiCli (line 71) | public final class TsunamiCli {
method TsunamiCli (line 80) | @Inject
method run (line 94) | public boolean run()
method hasSuccessfulResults (line 123) | private static boolean hasSuccessfulResults(ScanResults scanResults) {
method buildScanTarget (line 128) | private ScanTarget buildScanTarget() {
method saveResults (line 150) | private void saveResults(ScanResults scanResults) throws IOException {
class TsunamiCliFirstStageModule (line 154) | private static final class TsunamiCliFirstStageModule extends Abstract...
method TsunamiCliFirstStageModule (line 159) | TsunamiCliFirstStageModule(
method configure (line 166) | @Override
class TsunamiCliModule (line 174) | private static final class TsunamiCliModule extends AbstractModule {
method TsunamiCliModule (line 179) | TsunamiCliModule(
method configure (line 186) | @Override
method extractPluginServerArgs (line 209) | private ImmutableList<LanguageServerCommand> extractPluginServerArgs(
method extractOutputDir (line 274) | private String extractOutputDir(ScanResultsArchiver.Options sra) {
method doMain (line 282) | public static int doMain(String[] args) {
method main (line 316) | public static void main(String[] args) {
method loadConfig (line 320) | private static TsunamiConfig loadConfig() {
FILE: main/src/main/java/com/google/tsunami/main/cli/option/MainCliOptions.java
class MainCliOptions (line 28) | @Parameters(separators = "=")
method validate (line 63) | @Override
method getLogId (line 97) | public String getLogId() {
FILE: main/src/main/java/com/google/tsunami/main/cli/option/OutputDataFormat.java
type OutputDataFormat (line 22) | public enum OutputDataFormat {
method parse (line 32) | public static Optional<OutputDataFormat> parse(String value) {
FILE: main/src/main/java/com/google/tsunami/main/cli/option/validator/IpV4Validator.java
class IpV4Validator (line 22) | public class IpV4Validator extends IpValidator {
method ipVersion (line 24) | @Override
method shouldAccept (line 29) | @Override
FILE: main/src/main/java/com/google/tsunami/main/cli/option/validator/IpV6Validator.java
class IpV6Validator (line 22) | public class IpV6Validator extends IpValidator {
method ipVersion (line 24) | @Override
method shouldAccept (line 29) | @Override
FILE: main/src/main/java/com/google/tsunami/main/cli/option/validator/IpValidator.java
class IpValidator (line 25) | public abstract class IpValidator implements IParameterValidator {
method validate (line 27) | @Override
method ipVersion (line 39) | protected abstract int ipVersion();
method shouldAccept (line 41) | protected abstract boolean shouldAccept(InetAddress inetAddress);
FILE: main/src/main/java/com/google/tsunami/main/cli/server/RemoteServerLoader.java
class RemoteServerLoader (line 37) | public class RemoteServerLoader {
method RemoteServerLoader (line 42) | @Inject
method runServerProcesses (line 47) | public ImmutableList<Process> runServerProcesses() {
method getCommand (line 70) | private String getCommand(String flag, Object command) {
method runProcess (line 74) | private Optional<Process> runProcess(CommandExecutor executor) {
FILE: main/src/main/java/com/google/tsunami/main/cli/server/RemoteServerLoaderModule.java
class RemoteServerLoaderModule (line 26) | public final class RemoteServerLoaderModule extends AbstractModule {
method RemoteServerLoaderModule (line 30) | public RemoteServerLoaderModule(ImmutableList<LanguageServerCommand> c...
method provideLanguageServerCommands (line 34) | @Provides
FILE: main/src/test/java/com/google/tsunami/main/cli/LanguageServerOptionsTest.java
class LanguageServerOptionsTest (line 27) | @RunWith(JUnit4.class)
method validate_whenPluginServerFilenameDoesNotExist_throwsParameterException (line 30) | @Test
method validate_whenPortNumberNotInteger_throwsParameterException (line 39) | @Test
method validate_whenPortNumberOutOfRange_throwsParameterException (line 48) | @Test
method validate_whenPythonPluginServerPortNumberOutOfRange_throwsParameterException (line 63) | @Test
method validate_whenPythonPluginServerInvalidNumberOfDeadlines_throwsParameterException (line 78) | @Test
method validate_whenPythonPluginServerValidNumberOfDeadlines_succeeds (line 92) | @Test
FILE: main/src/test/java/com/google/tsunami/main/cli/ScanResultsArchiverTest.java
class ScanResultsArchiverTest (line 51) | @RunWith(JUnit4.class)
method setUp (line 69) | @Before
method optionsValidate_whenInvalidGcsUrl_throwsParameterException (line 92) | @Test
method optionsValidate_defaultLoggingEnabled_isFalse (line 98) | @Test
method archive_withNoStorageEnabled_storesNothing (line 103) | @Test
method archive_withLocalFileEnabledForJsonOutput_storesStringDataLocally (line 114) | @Test
method archive_withLocalFileEnabledForBinProtoOutput_storesBytesDataLocally (line 130) | @Test
method archive_withGcsEnabledForJsonOutput_uploadsStringDataToGcs (line 146) | @Test
method archive_withGcsEnabledForBinProtoOutput_uploadsBytesDataToGcs (line 165) | @Test
method archive_withLocalAndGcsOptionEnabled_archivesToBothLocation (line 183) | @Test
method parseJsonScanResults (line 205) | private static ScanResults parseJsonScanResults(String jsonScanResults)
FILE: main/src/test/java/com/google/tsunami/main/cli/TsunamiCliTest.java
class TsunamiCliTest (line 86) | @RunWith(JUnit4.class)
method runCli (line 101) | private boolean runCli(ImmutableMap<String, Object> rawConfigData, Str...
method run_whenIpTarget_generatesAndArchivesCorrectResult (line 128) | @Test
method run_whenHostnameTarget_generatesAndArchivesCorrectResult (line 163) | @Test
method run_whenUriTarget_generatesCorrectResult (line 202) | @Test
method run_whenIpAndHostnameTarget_generatesCorrectResult (line 245) | @Test
method run_whenScanFailed_generatesFailedScanResults (line 274) | @Test
method run_whenAdvisoryMode_generatesAdvisories (line 315) | @Test
method buildScanFindingFromDetectionReport (line 348) | private static ScanFinding buildScanFindingFromDetectionReport(Detecti...
FILE: main/src/test/java/com/google/tsunami/main/cli/option/MainCliOptionsTest.java
class MainCliOptionsTest (line 26) | @RunWith(JUnit4.class)
method validate_whenDumpAdvisoriesPathPassed_doesNotThrowParameterException (line 29) | @Test
method validate_whenMissingScanTarget_throwsParameterException (line 37) | @Test
method validate_whenUriTargetPassedWithHostnameTarget_throwsParameterException (line 44) | @Test
FILE: main/src/test/java/com/google/tsunami/main/cli/option/OutputDataFormatTest.java
class OutputDataFormatTest (line 25) | @RunWith(JUnit4.class)
method parse_whenStringMatchesExactly_returnsParsedOutputDataFormat (line 28) | @Test
method parse_whenStringMatchesIgnoringCases_returnsParsedOutputDataFormat (line 34) | @Test
method parse_whenStringNotMatch_returnsEmpty (line 40) | @Test
FILE: main/src/test/java/com/google/tsunami/main/cli/option/validator/IpV4ValidatorTest.java
class IpV4ValidatorTest (line 23) | @RunWith(JUnit4.class)
method flagName (line 26) | @Override
method getValidator (line 31) | @Override
method validIps (line 36) | @Override
method invalidIps (line 41) | @Override
FILE: main/src/test/java/com/google/tsunami/main/cli/option/validator/IpV6ValidatorTest.java
class IpV6ValidatorTest (line 23) | @RunWith(JUnit4.class)
method flagName (line 26) | @Override
method getValidator (line 31) | @Override
method validIps (line 36) | @Override
method invalidIps (line 51) | @Override
FILE: main/src/test/java/com/google/tsunami/main/cli/option/validator/IpValidatorTest.java
class IpValidatorTest (line 26) | public abstract class IpValidatorTest {
method validate_withValidIpValue_doesNotThrows (line 28) | @Test
method validate_withInvalidIpValue_throwsParameterException (line 39) | @Test
method flagName (line 54) | protected abstract String flagName();
method getValidator (line 56) | protected abstract IpValidator getValidator();
method validIps (line 58) | protected abstract ImmutableList<String> validIps();
method invalidIps (line 60) | protected abstract ImmutableList<String> invalidIps();
FILE: main/src/test/java/com/google/tsunami/main/cli/server/RemoteServerLoaderTest.java
class RemoteServerLoaderTest (line 28) | @RunWith(JUnit4.class)
method runServerProcess_whenPathExistsAndNormalPort_returnsValidProcessList (line 31) | @Test
method runServerProcess_whenServerAddressExistsAndNormalPort_returnsEmptyProcessList (line 56) | @Test
FILE: plugin/src/main/java/com/google/tsunami/plugin/LanguageServerException.java
class LanguageServerException (line 22) | public final class LanguageServerException extends TsunamiException {
method LanguageServerException (line 24) | public LanguageServerException(String message) {
method LanguageServerException (line 28) | public LanguageServerException(String message, Throwable cause) {
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginBootstrapModule.java
class PluginBootstrapModule (line 30) | public abstract class PluginBootstrapModule extends AbstractModule {
method configure (line 35) | @Override
method configurePlugin (line 47) | protected abstract void configurePlugin();
method registerPlugin (line 54) | protected final void registerPlugin(Class<? extends TsunamiPlugin> tsu...
method registerDynamicPlugin (line 71) | protected final void registerDynamicPlugin(
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginDefinition.java
class PluginDefinition (line 32) | @AutoValue
method type (line 34) | abstract PluginType type();
method name (line 36) | abstract String name();
method author (line 38) | abstract String author();
method version (line 40) | abstract String version();
method targetServiceName (line 42) | abstract Optional<ForServiceName> targetServiceName();
method targetSoftware (line 44) | abstract Optional<ForSoftware> targetSoftware();
method isForWebService (line 46) | abstract boolean isForWebService();
method targetOperatingSystemClass (line 48) | abstract Optional<ForOperatingSystemClass> targetOperatingSystemClass();
method requiresCallbackServer (line 50) | abstract boolean requiresCallbackServer();
method id (line 57) | @Memoized
method forPlugin (line 68) | public static PluginDefinition forPlugin(Class<? extends TsunamiPlugin...
method forRemotePlugin (line 104) | public static PluginDefinition forRemotePlugin(PluginInfo remotePlugin...
method forDynamicPlugin (line 130) | public static PluginDefinition forDynamicPlugin(
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginExecutionException.java
class PluginExecutionException (line 22) | public final class PluginExecutionException extends TsunamiException {
method PluginExecutionException (line 24) | public PluginExecutionException(String message) {
method PluginExecutionException (line 28) | public PluginExecutionException(String message, Throwable cause) {
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginExecutionModule.java
class PluginExecutionModule (line 22) | public final class PluginExecutionModule extends AbstractModule {
method configure (line 24) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginExecutionResult.java
class PluginExecutionResult (line 24) | @AutoValue
type ExecutionStatus (line 27) | public enum ExecutionStatus {
method isSucceeded (line 33) | public boolean isSucceeded() {
method executionStatus (line 37) | public abstract ExecutionStatus executionStatus();
method resultData (line 38) | public abstract Optional<T> resultData();
method executionStopwatch (line 39) | public abstract Stopwatch executionStopwatch();
method exception (line 40) | public abstract Optional<PluginExecutionException> exception();
method executorConfig (line 41) | public abstract PluginExecutorConfig<T> executorConfig();
method builder (line 43) | public static <T> Builder<T> builder() {
class Builder (line 48) | @AutoValue.Builder
method setExecutionStatus (line 50) | public abstract Builder<T> setExecutionStatus(ExecutionStatus execut...
method setResultData (line 51) | public abstract Builder<T> setResultData(T resultData);
method setExecutionStopwatch (line 52) | public abstract Builder<T> setExecutionStopwatch(Stopwatch execution...
method setException (line 53) | public abstract Builder<T> setException(PluginExecutionException exc...
method setExecutorConfig (line 54) | public abstract Builder<T> setExecutorConfig(PluginExecutorConfig<T>...
method build (line 56) | public abstract PluginExecutionResult<T> build();
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginExecutor.java
type PluginExecutor (line 24) | public interface PluginExecutor {
method executeAsync (line 32) | <T> ListenableFuture<PluginExecutionResult<T>> executeAsync(
class PluginExecutorConfig (line 36) | @AutoValue
method matchedPlugin (line 38) | @SuppressWarnings("rawtypes") // AutoValue bug for not handling gen...
method pluginExecutionLogic (line 40) | public abstract Callable<T> pluginExecutionLogic();
method builder (line 42) | public static <T> Builder<T> builder() {
class Builder (line 46) | @AutoValue.Builder
method setMatchedPlugin (line 48) | @SuppressWarnings("rawtypes") // AutoValue bug for not handling g...
method setPluginExecutionLogic (line 50) | public abstract Builder<T> setPluginExecutionLogic(Callable<T> plu...
method build (line 52) | public abstract PluginExecutorConfig<T> build();
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginExecutorImpl.java
class PluginExecutorImpl (line 30) | class PluginExecutorImpl implements PluginExecutor {
method PluginExecutorImpl (line 35) | @Inject
method PluginExecutorImpl (line 41) | PluginExecutorImpl(
method executeAsync (line 47) | @Override
method buildSucceededResult (line 68) | private <T> PluginExecutionResult<T> buildSucceededResult(
method buildFailedResult (line 85) | private <T> PluginExecutionResult<T> buildFailedResult(
method wrapException (line 100) | private static <T> PluginExecutionException wrapException(
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginExecutorModule.java
class PluginExecutorModule (line 21) | public final class PluginExecutorModule extends AbstractModule {
method configure (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginLoadingModule.java
class PluginLoadingModule (line 36) | public final class PluginLoadingModule extends AbstractModule {
method PluginLoadingModule (line 46) | public PluginLoadingModule(ScanResult classScanResult) {
method PluginLoadingModule (line 50) | @VisibleForTesting
method configure (line 56) | @Override
method newPluginBootstrapModule (line 79) | private PluginBootstrapModule newPluginBootstrapModule(ClassInfo tsuna...
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginManager.java
class PluginManager (line 45) | public class PluginManager {
method PluginManager (line 51) | @Inject
method getDetectorNames (line 62) | private static ImmutableSet<String> getDetectorNames(String detectorNa...
method getPortScanners (line 75) | public ImmutableList<PluginMatchingResult<PortScanner>> getPortScanner...
method getPortScanner (line 92) | public Optional<PluginMatchingResult<PortScanner>> getPortScanner() {
method getServiceFingerprinter (line 104) | public Optional<PluginMatchingResult<ServiceFingerprinter>> getService...
method getVulnDetectors (line 119) | public ImmutableList<PluginMatchingResult<VulnDetector>> getVulnDetect...
method getAllVulnDetectors (line 130) | public ImmutableList<VulnDetector> getAllVulnDetectors() {
method isPluginListed (line 144) | private static boolean isPluginListed(
method filterPluginByCliOptions (line 152) | private boolean filterPluginByCliOptions(PluginDefinition pluginDefini...
method isVulnDetector (line 157) | private static boolean isVulnDetector(PluginDefinition pluginDefinitio...
method matchCurrentCallbackServerSetup (line 162) | private boolean matchCurrentCallbackServerSetup(PluginDefinition plugi...
method matchAllVulnDetectors (line 170) | private static Optional<PluginMatchingResult<VulnDetector>> matchAllVu...
method matchVulnDetectors (line 180) | private static Optional<PluginMatchingResult<VulnDetector>> matchVulnD...
method matchRemoteVulnDetectors (line 221) | private static Optional<PluginMatchingResult<VulnDetector>> matchRemot...
method hasMatchingOperatingSystem (line 267) | private static boolean hasMatchingOperatingSystem(
method hasMatchingOperatingSystem (line 274) | private static boolean hasMatchingOperatingSystem(
method hasMatchingOperatingSystem (line 281) | private static boolean hasMatchingOperatingSystem(
method hasMatchingServiceName (line 301) | private static boolean hasMatchingServiceName(
method hasMatchingServiceName (line 315) | private static boolean hasMatchingServiceName(
method hasMatchingSoftware (line 330) | private static boolean hasMatchingSoftware(
method hasMatchingSoftware (line 339) | private static boolean hasMatchingSoftware(
class PluginMatchingResult (line 349) | @AutoValue
method pluginDefinition (line 351) | public abstract PluginDefinition pluginDefinition();
method tsunamiPlugin (line 353) | public abstract T tsunamiPlugin();
method matchedServices (line 355) | public abstract ImmutableList<NetworkService> matchedServices();
method pluginId (line 357) | public String pluginId() {
method builder (line 361) | public static <T extends TsunamiPlugin> Builder<T> builder() {
class Builder (line 366) | @SuppressWarnings("CanIgnoreReturnValueSuggester")
method setPluginDefinition (line 369) | public abstract Builder<T> setPluginDefinition(PluginDefinition va...
method setTsunamiPlugin (line 371) | public abstract Builder<T> setTsunamiPlugin(T value);
method matchedServicesBuilder (line 373) | abstract ImmutableList.Builder<NetworkService> matchedServicesBuil...
method addMatchedService (line 375) | public Builder<T> addMatchedService(NetworkService networkService) {
method addAllMatchedServices (line 380) | public Builder<T> addAllMatchedServices(Iterable<NetworkService> n...
method build (line 385) | public abstract PluginMatchingResult<T> build();
method getTargetOperatingSystemClass (line 389) | private static TargetOperatingSystemClass getTargetOperatingSystemClass(
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginManagerCliOptions.java
class PluginManagerCliOptions (line 34) | @Parameters(separators = "=")
method validate (line 51) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginServiceClient.java
class PluginServiceClient (line 39) | public final class PluginServiceClient {
method PluginServiceClient (line 44) | PluginServiceClient(Channel channel) {
method runWithDeadline (line 56) | public ListenableFuture<RunResponse> runWithDeadline(RunRequest reques...
method runCompactWithDeadline (line 67) | public ListenableFuture<RunResponse> runCompactWithDeadline(
method listPluginsWithDeadline (line 79) | public ListenableFuture<ListPluginsResponse> listPluginsWithDeadline(
method checkHealthWithDeadline (line 91) | public ListenableFuture<HealthCheckResponse> checkHealthWithDeadline(
FILE: plugin/src/main/java/com/google/tsunami/plugin/PluginType.java
type PluginType (line 19) | public enum PluginType {
FILE: plugin/src/main/java/com/google/tsunami/plugin/PortScanner.java
type PortScanner (line 28) | public interface PortScanner extends TsunamiPlugin {
method scan (line 36) | PortScanningReport scan(ScanTarget scanTarget);
FILE: plugin/src/main/java/com/google/tsunami/plugin/RemoteVulnDetector.java
type RemoteVulnDetector (line 26) | public interface RemoteVulnDetector extends VulnDetector {
method getAllPlugins (line 34) | ImmutableList<PluginDefinition> getAllPlugins();
method addMatchedPluginToDetect (line 42) | void addMatchedPluginToDetect(MatchedPlugin pluginToRun);
FILE: plugin/src/main/java/com/google/tsunami/plugin/RemoteVulnDetectorImpl.java
class RemoteVulnDetectorImpl (line 48) | public final class RemoteVulnDetectorImpl implements RemoteVulnDetector {
method RemoteVulnDetectorImpl (line 65) | RemoteVulnDetectorImpl(
method detect (line 74) | @Override
method getAdvisories (line 104) | @Override
method getAllPlugins (line 110) | @Override
method checkHealthWithBackoffs (line 133) | private boolean checkHealthWithBackoffs() {
method addMatchedPluginToDetect (line 173) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/RemoteVulnDetectorLoadingModule.java
class RemoteVulnDetectorLoadingModule (line 36) | public final class RemoteVulnDetectorLoadingModule extends AbstractModule {
method RemoteVulnDetectorLoadingModule (line 58) | public RemoteVulnDetectorLoadingModule(ImmutableList<LanguageServerCom...
method configure (line 62) | @Override
method getLanguageServerChannel (line 79) | private Channel getLanguageServerChannel(LanguageServerCommand command) {
method getRemoteVulnDetectorPluginDefinition (line 97) | @VisibleForTesting
type PluginInfoBuilder (line 111) | @AutoBuilder(callMethod = "pluginInfo")
method type (line 113) | PluginInfoBuilder type(PluginType type);
method name (line 115) | PluginInfoBuilder name(String name);
method description (line 117) | PluginInfoBuilder description(String description);
method author (line 119) | PluginInfoBuilder author(String author);
method version (line 121) | PluginInfoBuilder version(String version);
method bootstrapModule (line 123) | PluginInfoBuilder bootstrapModule(Class<? extends PluginBootstrapMod...
method build (line 125) | PluginInfo build();
method pluginInfo (line 129) | @SuppressWarnings("unused")
method pluginInfoBuilder (line 142) | static PluginInfoBuilder pluginInfoBuilder() {
class RemoteVulnDetectorBootstrapLoadingModule (line 146) | private static class RemoteVulnDetectorBootstrapLoadingModule extends ...
method configurePlugin (line 147) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/ServiceFingerprinter.java
type ServiceFingerprinter (line 32) | public interface ServiceFingerprinter extends TsunamiPlugin {
method fingerprint (line 43) | FingerprintingReport fingerprint(TargetInfo targetInfo, NetworkService...
FILE: plugin/src/main/java/com/google/tsunami/plugin/TcsClient.java
class TcsClient (line 38) | public final class TcsClient {
method TcsClient (line 49) | public TcsClient(
method isCallbackServerEnabled (line 64) | public boolean isCallbackServerEnabled() {
method getCallbackUri (line 73) | public String getCallbackUri(String secretString) {
method getCallbackAddress (line 95) | public String getCallbackAddress() {
method getCallbackPort (line 106) | public int getCallbackPort() {
method hasOobLog (line 114) | public boolean hasOobLog(String secretString) {
method sendPollingRequest (line 128) | private Optional<PollingResult> sendPollingRequest(String secretString) {
method isValidPortNumber (line 149) | private static boolean isValidPortNumber(int port) {
FILE: plugin/src/main/java/com/google/tsunami/plugin/TcsClientCliOptions.java
class TcsClientCliOptions (line 23) | @Parameters(separators = "=")
method validate (line 39) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/TcsConfigProperties.java
class TcsConfigProperties (line 21) | @ConfigProperties("plugin.callbackserver")
FILE: plugin/src/main/java/com/google/tsunami/plugin/TsunamiPlugin.java
type TsunamiPlugin (line 24) | public interface TsunamiPlugin {}
FILE: plugin/src/main/java/com/google/tsunami/plugin/VulnDetector.java
type VulnDetector (line 31) | public interface VulnDetector extends TsunamiPlugin {
method detect (line 41) | DetectionReportList detect(
method getAdvisories (line 50) | abstract ImmutableList<Vulnerability> getAdvisories();
FILE: plugin/src/main/java/com/google/tsunami/plugin/payload/NotImplementedException.java
class NotImplementedException (line 30) | public final class NotImplementedException extends RuntimeException {
method NotImplementedException (line 32) | @FormatMethod
FILE: plugin/src/main/java/com/google/tsunami/plugin/payload/Payload.java
class Payload (line 25) | public class Payload {
method Payload (line 33) | public Payload(
method getPayload (line 49) | public final String getPayload() {
method checkIfExecuted (line 62) | public final boolean checkIfExecuted(String input) {
method checkIfExecuted (line 72) | public final boolean checkIfExecuted(ByteString input) {
method checkIfExecuted (line 82) | public final boolean checkIfExecuted(Optional<ByteString> input) {
method checkIfExecuted (line 92) | public final boolean checkIfExecuted() {
method getPayloadAttributes (line 101) | public final PayloadAttributes getPayloadAttributes() {
FILE: plugin/src/main/java/com/google/tsunami/plugin/payload/PayloadGenerator.java
class PayloadGenerator (line 33) | public final class PayloadGenerator {
method PayloadGenerator (line 42) | @Inject
method isCallbackServerEnabled (line 52) | public boolean isCallbackServerEnabled() {
method generate (line 65) | public Payload generate(PayloadGeneratorConfig config) {
method generateNoCallback (line 69) | public Payload generateNoCallback(PayloadGeneratorConfig config) {
method generatePayload (line 73) | private Payload generatePayload(PayloadGeneratorConfig config, boolean...
method isMatchingPayload (line 106) | private boolean isMatchingPayload(PayloadDefinition p, PayloadGenerato...
method convertParsedPayload (line 112) | private Payload convertParsedPayload(PayloadDefinition p, PayloadGener...
FILE: plugin/src/main/java/com/google/tsunami/plugin/payload/PayloadGeneratorModule.java
class PayloadGeneratorModule (line 54) | public final class PayloadGeneratorModule extends AbstractModule {
method PayloadGeneratorModule (line 57) | public PayloadGeneratorModule(SecureRandom secureRng) {
method providesCallbackAddress (line 76) | @Provides
method providesCallbackPort (line 86) | @Provides
method providesCallbackPollingUri (line 95) | @Provides
method providesTcsClient (line 104) | @Provides
method providesPayloadSecretGenerator (line 127) | @Provides
method provideParsedPayloads (line 132) | @Provides
method validatePayloads (line 156) | ImmutableList<PayloadDefinition> validatePayloads(List<PayloadDefiniti...
FILE: plugin/src/main/java/com/google/tsunami/plugin/payload/PayloadSecretGenerator.java
class PayloadSecretGenerator (line 29) | public final class PayloadSecretGenerator {
method PayloadSecretGenerator (line 33) | @Inject
method generate (line 38) | public String generate(int secretLength) {
method getModule (line 44) | public static PayloadSecretGeneratorModule getModule() {
class PayloadSecretGeneratorModule (line 48) | private static final class PayloadSecretGeneratorModule extends Abstra...
method providesPayloadSecretRng (line 49) | @Provides
FILE: plugin/src/main/java/com/google/tsunami/plugin/payload/Validator.java
type Validator (line 22) | @FunctionalInterface
method isExecuted (line 30) | boolean isExecuted(Optional<ByteString> input);
FILE: plugin/src/main/java/com/google/tsunami/plugin/payload/testing/FakePayloadGeneratorModule.java
class FakePayloadGeneratorModule (line 33) | public final class FakePayloadGeneratorModule extends AbstractModule {
method FakePayloadGeneratorModule (line 43) | FakePayloadGeneratorModule(
method configure (line 52) | @Override
method builder (line 63) | public static Builder builder() {
method build (line 67) | static FakePayloadGeneratorModule build(
class Builder (line 74) | @AutoBuilder(callMethod = "build")
method builder (line 76) | public static Builder builder() {
method setCallbackServer (line 80) | public abstract Builder setCallbackServer(MockWebServer callbackServ...
method setSecureRng (line 82) | public abstract Builder setSecureRng(SecureRandom secureRng);
method build (line 84) | public abstract FakePayloadGeneratorModule build();
FILE: plugin/src/main/java/com/google/tsunami/plugin/payload/testing/PayloadTestHelper.java
class PayloadTestHelper (line 25) | public final class PayloadTestHelper {
method PayloadTestHelper (line 27) | private PayloadTestHelper() {}
method generateMockSuccessfulCallbackResponse (line 29) | public static MockResponse generateMockSuccessfulCallbackResponse() th...
method generateMockUnsuccessfulCallbackResponse (line 35) | public static MockResponse generateMockUnsuccessfulCallbackResponse() {
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FailedPortScanner.java
class FailedPortScanner (line 25) | @PluginInfo(
method scan (line 34) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FailedPortScannerBootstrapModule.java
class FailedPortScannerBootstrapModule (line 21) | public final class FailedPortScannerBootstrapModule extends PluginBootst...
method configurePlugin (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FailedRemoteVulnDetector.java
class FailedRemoteVulnDetector (line 33) | @PluginInfo(
method FailedRemoteVulnDetector (line 44) | public FailedRemoteVulnDetector() {
method getAdvisories (line 48) | @Override
method detect (line 53) | @Override
method getAllPlugins (line 58) | @Override
method addMatchedPluginToDetect (line 63) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FailedRemoteVulnDetectorBootstrapModule.java
class FailedRemoteVulnDetectorBootstrapModule (line 21) | public final class FailedRemoteVulnDetectorBootstrapModule extends Plugi...
method configurePlugin (line 22) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FailedServiceFingerprinter.java
class FailedServiceFingerprinter (line 27) | @PluginInfo(
method fingerprint (line 37) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FailedServiceFingerprinterBootstrapModule.java
class FailedServiceFingerprinterBootstrapModule (line 21) | public final class FailedServiceFingerprinterBootstrapModule extends Plu...
method configurePlugin (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FailedVulnDetector.java
class FailedVulnDetector (line 28) | @PluginInfo(
method getAdvisories (line 37) | @Override
method detect (line 42) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FailedVulnDetectorBootstrapModule.java
class FailedVulnDetectorBootstrapModule (line 21) | public final class FailedVulnDetectorBootstrapModule extends PluginBoots...
method configurePlugin (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakePluginExecutionModule.java
class FakePluginExecutionModule (line 26) | public final class FakePluginExecutionModule extends AbstractModule {
method configure (line 28) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakePortScanner.java
class FakePortScanner (line 30) | @PluginInfo(
method getFakeNetworkService (line 39) | public static NetworkService getFakeNetworkService(NetworkEndpoint net...
method scan (line 47) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakePortScanner2.java
class FakePortScanner2 (line 31) | @PluginInfo(
method getFakeNetworkService (line 40) | public static NetworkService getFakeNetworkService(NetworkEndpoint net...
method scan (line 49) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakePortScannerBootstrapModule.java
class FakePortScannerBootstrapModule (line 21) | public class FakePortScannerBootstrapModule extends PluginBootstrapModule {
method configurePlugin (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakePortScannerBootstrapModule2.java
class FakePortScannerBootstrapModule2 (line 21) | public class FakePortScannerBootstrapModule2 extends PluginBootstrapModu...
method configurePlugin (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakePortScannerBootstrapModuleEmpty.java
class FakePortScannerBootstrapModuleEmpty (line 21) | public class FakePortScannerBootstrapModuleEmpty extends PluginBootstrap...
method configurePlugin (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakePortScannerEmpty.java
class FakePortScannerEmpty (line 26) | @PluginInfo(
method scan (line 35) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakeRemoteVulnDetector.java
class FakeRemoteVulnDetector (line 42) | @com.google.tsunami.plugin.annotations.PluginInfo(
method FakeRemoteVulnDetector (line 56) | public FakeRemoteVulnDetector() {
method FakeRemoteVulnDetector (line 60) | public FakeRemoteVulnDetector(int fakePluginId) {
method getAdvisories (line 65) | @Override
method detect (line 70) | @Override
method getFakeDetectionReport (line 85) | public static DetectionReport getFakeDetectionReport(
method getAllPlugins (line 96) | @Override
method addMatchedPluginToDetect (line 110) | @Override
method getAdvisoriesStatic (line 115) | private static ImmutableList<Vulnerability> getAdvisoriesStatic() {
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakeRemoteVulnDetectorBootstrapModule.java
class FakeRemoteVulnDetectorBootstrapModule (line 25) | public final class FakeRemoteVulnDetectorBootstrapModule extends PluginB...
method configurePlugin (line 26) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakeServiceFingerprinter.java
class FakeServiceFingerprinter (line 30) | @PluginInfo(
method addWebServiceContext (line 42) | public static NetworkService addWebServiceContext(NetworkService netwo...
method fingerprint (line 51) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakeServiceFingerprinterBootstrapModule.java
class FakeServiceFingerprinterBootstrapModule (line 21) | public class FakeServiceFingerprinterBootstrapModule extends PluginBoots...
method configurePlugin (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakeVulnDetector.java
class FakeVulnDetector (line 35) | @PluginInfo(
method getFakeDetectionReport (line 43) | public static DetectionReport getFakeDetectionReport(
method getAdvisories (line 54) | @Override
method detect (line 59) | @Override
method getAdvisoriesStatic (line 70) | private static ImmutableList<Vulnerability> getAdvisoriesStatic() {
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakeVulnDetector2.java
class FakeVulnDetector2 (line 35) | @PluginInfo(
method getFakeDetectionReport (line 43) | public static DetectionReport getFakeDetectionReport(
method getAdvisories (line 54) | @Override
method detect (line 59) | @Override
method getAdvisoriesStatic (line 70) | private static ImmutableList<Vulnerability> getAdvisoriesStatic() {
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakeVulnDetectorBootstrapModule.java
class FakeVulnDetectorBootstrapModule (line 21) | public class FakeVulnDetectorBootstrapModule extends PluginBootstrapModu...
method configurePlugin (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakeVulnDetectorBootstrapModule2.java
class FakeVulnDetectorBootstrapModule2 (line 21) | public class FakeVulnDetectorBootstrapModule2 extends PluginBootstrapMod...
method configurePlugin (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakeVulnDetectorBootstrapModuleEmpty.java
class FakeVulnDetectorBootstrapModuleEmpty (line 21) | public class FakeVulnDetectorBootstrapModuleEmpty extends PluginBootstra...
method configurePlugin (line 23) | @Override
FILE: plugin/src/main/java/com/google/tsunami/plugin/testing/FakeVulnDetectorEmpty.java
class FakeVulnDetectorEmpty (line 28) | @PluginInfo(
method detect (line 37) | @Override
method getAdvisories (line 43) | @Override
FILE: plugin/src/test/java/com/google/tsunami/plugin/PluginDefinitionTest.java
class PluginDefinitionTest (line 29) | @RunWith(JUnit4.class)
method id_always_generatesCorrectPluginId (line 32) | @Test
method forPlugin_whenPluginHasNoAnnotation_throwsException (line 39) | @Test
method forRemotePlugin_always_generatesCorrectDefinition (line 45) | @Test
method forRemotePlugin_whenPassedNull_throwsException (line 58) | @Test
class NoAnnotationPlugin (line 63) | private static final class NoAnnotationPlugin implements TsunamiPlugin {}
FILE: plugin/src/test/java/com/google/tsunami/plugin/PluginExecutorImplTest.java
class PluginExecutorImplTest (line 35) | @RunWith(JUnit4.class)
method executeAsync_whenSucceeded_returnsSucceededResult (line 49) | @Test
method executeAsync_whenFailedWithPluginExecutionException_returnsFailedResult (line 69) | @Test
method executeAsync_whenFailedWithUnknownException_returnsFailedResult (line 94) | @Test
FILE: plugin/src/test/java/com/google/tsunami/plugin/PluginLoadingModuleTest.java
class PluginLoadingModuleTest (line 42) | @RunWith(JUnit4.class)
method configure_always_loadsAllTsunamiPlugins (line 56) | @Test
method configure_whenPluginMissingRequiredAnnotation_throwsException (line 87) | @Test
method configure_whenPluginBootstrapModuleCannotBeInitialized_throwsException (line 109) | @Test
class FakePortScanner (line 131) | @PluginInfo(
method scan (line 139) | @Override
class FakePortScannerBootstrapModule (line 145) | private static final class FakePortScannerBootstrapModule extends Plug...
method configurePlugin (line 146) | @Override
class FakeVulnDetector (line 152) | @PluginInfo(
method detect (line 160) | @Override
method getAdvisories (line 166) | @Override
class FakeVulnDetectorBootstrapModule (line 172) | private static final class FakeVulnDetectorBootstrapModule extends Plu...
method configurePlugin (line 173) | @Override
class FakeVulnDetector2 (line 179) | @PluginInfo(
method detect (line 187) | @Override
method getAdvisories (line 193) | @Override
class FakeVulnDetector2BootstrapModule (line 198) | static final class FakeVulnDetector2BootstrapModule extends PluginBo...
method configurePlugin (line 199) | @Override
class NoAnnotationDetector (line 206) | private static final class NoAnnotationDetector implements VulnDetector {
method detect (line 207) | @Override
method getAdvisories (line 213) | @Override
FILE: plugin/src/test/java/com/google/tsunami/plugin/PluginManagerTest.java
class PluginManagerTest (line 69) | @RunWith(JUnit4.class)
method getPortScanners_whenMultiplePortScannersInstalled_returnsAllPortScanners (line 72) | @Test
method getPortScanners_whenNoPortScannersInstalled_returnsEmptyList (line 92) | @Test
method getPortScanner_whenMultiplePortScannersInstalled_returnsTheFirstMatchedPortScanner (line 105) | @Test
method getPortScanner_whenNoPortScannersInstalled_returnsEmptyOptional (line 129) | @Test
method getServiceFingerprinter_whenFingerprinterNotAnnotated_returnsEmpty (line 142) | @Test
method getServiceFingerprinter_whenFingerprinterHasMatch_returnsMatch (line 164) | @Test
method getServiceFingerprinter_whenNoFingerprinterMatches_returnsEmpty (line 187) | @Test
method getServiceFingerprinter_whenForWebServiceAnnotationAndWebService_returnsMatch (line 209) | @Test
method getServiceFingerprinter_whenForWebServiceAnnotationAndNonWebService_returnsEmpty (line 241) | @Test
method getVulnDetectors_whenMultipleVulnDetectorsInstalledNoFiltering_returnsAllVulnDetector (line 267) | @Test
method getVulnDetectors_whenServiceNameFilterHasMatchingService_returnsMatchedService (line 311) | @Test
method getVulnDetectors_whenServiceNameFilterHasNoMatchingService_returnsEmpty (line 355) | @Test
method getVulnDetectors_whenSoftwareFilterHasMatchingService_returnsMatchedService (line 383) | @Test
method getVulnDetectors_whenOsFilterHasNoMatchingClass_returnsEmpty (line 430) | @Test
method getVulnDetectors_whenOsFilterHasMatchingClass_returnsMatches (line 474) | @Test
method getVulnDetectors_whenOsServiceFilterHasMatchingClass_returnsMatches (line 528) | @Test
method getVulnDetectors_whenSoftwareFilterHasNoMatchingService_returnsEmpty (line 583) | @Test
method getVulnDetectors_whenNoVulnDetectorsInstalled_returnsEmptyList (line 612) | @Test
method getVulnDetectors_whenRemotePluginsInstalledNoFiltering_returnsAllRemoteTsunamiPlugins (line 643) | @Test
method getVulnDetectors_whenRemoteDetectorServiceNameFilterHasMatchingService_returnsMatchedService (line 682) | @Test
method getVulnDetectors_whenRemoteDetectorWithServiceNameHasNoMatch_returnsNoServices (line 730) | @Test
method getVulnDetectors_whenRemoteDetectorSoftwareFilterHasMatchingService_returnsMatchedService (line 761) | @Test
method getVulnDetectors_whenRemoteDetectorOsFilterHasMatchingService_returnsMatchedService (line 825) | @Test
method getVulnDetectors_whenRemoteDetectorWithSoftwareFilterHasNoMatchingService_returnsNoServices (line 905) | @Test
method getVulnDetectors_whenDetectorsIncludeIsOverridden_returnsMatchingVulnDetector (line 941) | @Test
method getVulnDetectors_whenDetectorsExcludeIsOverridden_returnsMatchingVulnDetector (line 988) | @Test
class NoAnnotationFingerprinter (line 1035) | @PluginInfo(
method fingerprint (line 1043) | @Override
method getModule (line 1048) | static NoAnnotationFingerprinterBootstrapModule getModule() {
class NoAnnotationFingerprinterBootstrapModule (line 1052) | private static final class NoAnnotationFingerprinterBootstrapModule
method configurePlugin (line 1054) | @Override
class FakeWebFingerprinter (line 1061) | @PluginInfo(
method fingerprint (line 1070) | @Override
method getModule (line 1075) | static FakeWebFingerprinterBootstrapModule getModule() {
class FakeWebFingerprinterBootstrapModule (line 1079) | private static final class FakeWebFingerprinterBootstrapModule exten...
method configurePlugin (line 1080) | @Override
class FakeServiceNameFilteringDetector (line 1087) | @PluginInfo(
method detect (line 1097) | @Override
method getAdvisories (line 1103) | @Override
method getModule (line 1108) | static FakeServiceNameFilteringDetectorBootstrapModule getModule() {
class FakeServiceNameFilteringDetectorBootstrapModule (line 1112) | private static final class FakeServiceNameFilteringDetectorBootstrap...
method configurePlugin (line 1114) | @Override
class FakeSoftwareFilteringDetector (line 1121) | @PluginInfo(
method detect (line 1131) | @Override
method getAdvisories (line 1137) | @Override
method getModule (line 1142) | static FakeSofwareFilteringDetectorBootstrapModule getModule() {
class FakeSofwareFilteringDetectorBootstrapModule (line 1146) | private static final class FakeSofwareFilteringDetectorBootstrapModule
method configurePlugin (line 1148) | @Override
class FakeOsFilteringDetector (line 1155) | @PluginInfo(
method detect (line 1164) | @Override
method getAdvisories (line 1170) | @Override
method getModule (line 1175) | static FakeOsFilteringDetectorBootstrapModule getModule() {
class FakeOsFilteringDetectorBootstrapModule (line 1179) | private static final class FakeOsFilteringDetectorBootstrapModule
method configurePlugin (line 1181) | @Override
class FakeOsServiceFilteringDetector (line 1188) | @PluginInfo(
method detect (line 1199) | @Override
method getAdvisories (line 1205) | @Override
method getModule (line 1210) | static FakeOsServiceFilteringDetectorBootstrapModule getModule() {
class FakeOsServiceFilteringDetectorBootstrapModule (line 1214) | private static final class FakeOsServiceFilteringDetectorBootstrapMo...
method configurePlugin (line 1216) | @Override
class FakeFilteringRemoteDetector (line 1223) | @PluginInfo(
method FakeFilteringRemoteDetector (line 1235) | FakeFilteringRemoteDetector() {
method getMatchedPlugins (line 1239) | public ImmutableList<MatchedPlugin> getMatchedPlugins() {
method detect (line 1243) | @Override
method getAdvisories (line 1249) | @Override
method getAllPlugins (line 1254) | @Override
method addMatchedPluginToDetect (line 1263) | @Override
method getHttpServiceDefinition (line 1268) | static com.google.tsunami.proto.PluginDefinition getHttpServiceDefin...
method getJenkinsServiceDefinition (line 1281) | static com.google.tsunami.proto.PluginDefinition getJenkinsServiceDe...
method getOperatingSystemServiceDefinition (line 1294) | static com.google.tsunami.proto.PluginDefinition getOperatingSystemS...
method getOperatingSystemAndHttpServiceDefinition (line 1310) | static com.google.tsunami.proto.PluginDefinition getOperatingSystemA...
method getModule (line 1329) | static FakeFilteringRemoteDetectorBootstrapModule getModule() {
class FakeFilteringRemoteDetectorBootstrapModule (line 1333) | private static final class FakeFilteringRemoteDetectorBootstrapModule
method configurePlugin (line 1335) | @Override
class FakeRemoteVulnDetectorLoadingModule (line 1342) | private static final class FakeRemoteVulnDetectorLoadingModule extends...
method FakeRemoteVulnDetectorLoadingModule (line 1345) | public FakeRemoteVulnDetectorLoadingModule() {
method FakeRemoteVulnDetectorLoadingModule (line 1349) | public FakeRemoteVulnDetectorLoadingModule(int numRemotePlugins) {
method configure (line 1353) | @Override
FILE: plugin/src/test/java/com/google/tsunami/plugin/PluginServiceClientTest.java
class PluginServiceClientTest (line 57) | @RunWith(JUnit4.class)
method setUp (line 72) | @Before
method pluginService_isNotNull (line 87) | @Test
method run_invalidRequest_returnNoDetectionReports (line 92) | @Test
method run_singlePluginValidRequest_returnSingleDetectionReport (line 112) | @Test
method run_multiplePluginValidRequest_returnMultipleDetectionReports (line 139) | @Test
method listPlugins_returnsMultiplePlugins (line 202) | @Test
method checkHealth_returnServingHealthResponse (line 230) | @Test
method checkHealth_returnNotServingHealthResponse (line 253) | @Test
method assertRunResponseContainsAllRunRequestParameters (line 276) | private void assertRunResponseContainsAllRunRequestParameters(
method createSinglePluginDefinitionWithName (line 288) | private PluginDefinition createSinglePluginDefinitionWithName(String n...
method createSinglePluginRunRequest (line 300) | private RunRequest createSinglePluginRunRequest() {
FILE: plugin/src/test/java/com/google/tsunami/plugin/RemoteVulnDetectorImplTest.java
class RemoteVulnDetectorImplTest (line 55) | @RunWith(JUnit4.class)
method setUp (line 77) | @Before
method detect_withServingServer_returnsSuccessfulDetectionReportList (line 96) | @Test
method detect_withNonServingServer_returnsEmptyDetectionReportList (line 125) | @Test
method detect_withRpcError_throwsLanguageServerException (line 148) | @Test(timeout = 30000L)
method getAllPlugins_withServingServer_returnsSuccessfulList (line 159) | @Test
method getAllPlugins_withCompactRunRequest_callsRunCompact (line 178) | @Test
method getAllPlugins_withNonServingServer_returnsEmptyList (line 234) | @Test
method getAllPlugins_withRpcError_throwsLanguageServerException (line 240) | @Test(timeout = 30000L)
method getAllPlugins_withUnregisteredHealthService_throwsLanguageServerException (line 246) | @Test(timeout = 30000L)
method getNewRemoteVulnDetectorInstance (line 252) | private RemoteVulnDetector getNewRemoteVulnDetectorInstance() throws E...
method registerHealthCheckWithError (line 277) | private void registerHealthCheckWithError() {
method registerHealthCheckWithStatus (line 289) | private void registerHealthCheckWithStatus(ServingStatus status) {
method registerSuccessfulRunService (line 301) | private void registerSuccessfulRunService() {
method createSinglePluginDefinitionWithName (line 319) | private PluginDefinition createSinglePluginDefinitionWithName(String n...
FILE: plugin/src/test/java/com/google/tsunami/plugin/RemoteVulnDetectorLoadingModuleTest.java
class RemoteVulnDetectorLoadingModuleTest (line 32) | @RunWith(JUnit4.class)
method generateServerName (line 40) | private static String generateServerName() {
method configure_whenNoChannelsRegistered_loadsNoRemotePlugins (line 44) | @Test
method configure_always_loadsAllRemotePlugins (line 53) | @Test
FILE: plugin/src/test/java/com/google/tsunami/plugin/TcsClientTest.java
class TcsClientTest (line 38) | @RunWith(JUnit4.class)
method setup (line 53) | @Before
method getCallbackUri_validIpv4Address_returnsUriWithCbidInPath (line 58) | @Test
method getCallbackUri_validIpv6Address_returnsUriWithCbidInPath (line 69) | @Test
method getCallbackUri_validDomainAddress_returnsUriWithCbidInSubdomain (line 80) | @Test
method getCallbackUri_callbackPortIs80_returnsUriWithoutPortNum (line 90) | @Test
method getCallbackUri_invalidAddress_throwsError (line 100) | @Test
method getCallbackUri_invalidCallbackPort_throwsError (line 107) | @Test
method getCallbackAddress_validIpv4Address_returnsAddress (line 113) | @Test
method getCallbackAddress_validIpv6Address_returnsAddress (line 119) | @Test
method getCallbackAddress_validDomainAddress_returnsAddress (line 125) | @Test
method getCallbackAddress_invalidAddress_throwsError (line 131) | @Test
method getCallbackPort_validPort_returnsPort (line 137) | @Test
method getCallbackPort_invalidPort_throwsError (line 143) | @Test
method isVulnerable_sendsValidPollingRequest (line 149) | @Test
method isVulnerable_validLogRecordWithHttpLogged_returnsTrue (line 162) | @Test
method isVulnerable_validLogRecordWithNothingLogged_returnsFalse (line 176) | @Test
method isVulnerable_noLogRecordFetched_returnsFalse (line 190) | @Test
method isVulnerable_requestFailed_returnsFalse (line 203) | @Test
FILE: plugin/src/test/java/com/google/tsunami/plugin/payload/PayloadGeneratorModuleTest.java
class PayloadGeneratorModuleTest (line 50) | @RunWith(Parameterized.class)
method setUp (line 87) | @Before
method providesTcsClient_withNoConfig_returnsInvalidTcsClient (line 95) | @Test
method providesTcsClient_withGoodConfig_returnsValidTcsClient (line 102) | @Test
method providesTcsClient_withConfigPropertiesAndCliOptions_prioritizesCliOptions (line 109) | @Test
method data (line 139) | @Parameters
method providesTcsClient_withBadConfig_throwsException (line 151) | @Test
method provideParsedPayloads_returnsSomePayloads (line 160) | @Test
method validatePayloads_withGoodPayloads_returnsPayloads (line 167) | @Test
method validatePayloads_withoutInterpretationEnvironment_throwsException (line 177) | @Test
method validatePayloads_withoutExecutionEnvironment_throwsException (line 188) | @Test
method validatePayloads_withoutVulnerabilityType_throwsException (line 198) | @Test
method validatePayloads_withoutPayloadString_throwsException (line 208) | @Test
method validatePayloads_withCallbackPayloadWithoutUrlToken_throwsException (line 218) | @Test
method validatePayloads_withNoCallbackPayloadWithoutValidationType_throwsException (line 230) | @Test
method validatePayloads_withRegexValidationWithoutValidationRegex_throwsException (line 241) | @Test
FILE: plugin/src/test/java/com/google/tsunami/plugin/payload/PayloadGeneratorWithCallbackServerTest.java
class PayloadGeneratorWithCallbackServerTest (line 39) | @RunWith(JUnit4.class)
method nextBytes (line 47) | @Override
method setUp (line 99) | @Before
method isCallbackServerEnabled_returnsTrue (line 112) | @Test
method generate_withLinuxConfiguration_returnsCurlPayload (line 117) | @Test
method generate_withLinuxConfiguration_returnsPrintfPayload (line 127) | @Test
method checkIfExecuted_withLinuxConfiguration_andExecutedCallbackUrl_returnsTrue (line 135) | @Test
method checkIfExecuted_withLinuxConfiguration_andNotExecutedCallbackUrl_returnsFalse (line 145) | @Test
method generate_withCrontabConfiguration_returnsCronCurlPayload (line 154) | @Test
method checkIfExecuted_withCrontabConfiguration_andExecutedCallbackUrl_returnsTrue (line 164) | @Test
method checkIfExecuted_withCrontabConfiguration_andNotExecutedCallbackUrl_returnsFalse (line 174) | @Test
method generate_withCurlTraceConfiguration_returnsCurlTracePayload (line 183) | @Test
method generate_withWindowsConfiguration_returnsEchoPayload (line 191) | @Test
method checkIfExecuted_withWindowsConfiguration_andExecutedCallbackUrl_returnsTrue (line 199) | @Test
method checkIfExecuted_withWindowsConfiguration_andNotExecutedCallbackUrl_returnsFalse (line 209) | @Test
method getPayload_withSsrfConfiguration_returnsCallbackUrl (line 218) | @Test
method checkIfExecuted_withSsrfConfiguration_andExecutedUrl_returnsTrue (line 227) | @Test
method getPayload_withSsrfConfiguration_andNotExecutedUrl_returnsFalse (line 236) | @Test
method generate_withoutVulnerabilityType_throwsNotImplementedException (line 244) | @Test
method generate_withoutInterpretationEnvironment_throwsNotImplementedException (line 258) | @Test
method generate_withoutExecutionEnvironment_throwsNotImplementedException (line 271) | @Test
method generate_withoutConfig_throwsNotImplementedException (line 284) | @Test
FILE: plugin/src/test/java/com/google/tsunami/plugin/payload/PayloadGeneratorWithoutCallbackServerTest.java
class PayloadGeneratorWithoutCallbackServerTest (line 38) | @RunWith(JUnit4.class)
method nextBytes (line 46) | @Override
method setUp (line 112) | @Before
method isCallbackServerEnabled_returnsFalse (line 120) | @Test
method getNonCallbackPayload_withLinuxConfiguration_returnsPrintfPayload (line 125) | @Test
method getPayload_withLinuxConfiguration_returnsPrintfPayload (line 133) | @Test
method checkIfExecuted_withLinuxConfiguration_andCorrectInput_returnsTrue (line 141) | @Test
method checkIfExecuted_withLinuxConfiguration_andIncorectInput_returnsFalse (line 151) | @Test
method generateNonCallbackPayload_withCrontabConfiguration_throwsNotImplementedException (line 158) | @Test
method getNonCallbackPayload_withBlindRceReadConfiguration_returnsCurlTracePayload (line 166) | @Test
method getPayload_withBlindRceReadConfiguration_returnsCurlTracePayload (line 174) | @Test
method checkIfExecuted_withBlindRceReadConfiguration_andCorrectInput_returnsTrue (line 182) | @Test
method checkIfExecuted_withBlindRceReadConfiguration_andIncorectInput_returnsFalse (line 191) | @Test
method getNonCallbackPayload_withWindowsConfiguration_returnsPrintfPayload (line 198) | @Test
method getPayload_withWindowsConfiguration_returnsEchoPayload (line 206) | @Test
method checkIfExecuted_withWindowsConfiguration_andCorrectInput_returnsTrue (line 214) | @Test
method checkIfExecuted_withWindowsConfiguration_andIncorectInput_returnsFalse (line 224) | @Test
method getPayload_withJavaConfiguration_returnsPrintfPayload (line 231) | @Test
method checkIfExecuted_withJavaConfiguration_andCorrectInput_returnsTrue (line 241) | @Test
method checkIfExecuted_withJavaConfiguration_andIncorrectInput_returnsFalse (line 251) | @Test
method getPayload_withJspConfiguration_returnsPrintfPayload (line 260) | @Test
method checkIfExecuted_withJspConfiguration_andCorrectInput_returnsTrue (line 271) | @Test
method checkIfExecuted_withJspConfiguration_andIncorrectInput_returnsFalse (line 281) | @Test
method getPayload_withSsrfConfiguration_returnsGooglePayload (line 290) | @Test
method checkIfExecuted_withSsrfConfiguration_andCorrectInput_returnsTrue (line 298) | @Test
method checkIfExecuted_withSsrfConfiguration_andIncorrectInput_returnsFalse (line 305) | @Test
method generate_withoutVulnerabilityType_throwsNotImplementedException (line 312) | @Test
method generate_withoutInterpretationEnvironment_throwsNotImplementedException (line 326) | @Test
method generate_withoutExecutionEnvironment_throwsNotImplementedException (line 339) | @Test
method generate_withoutConfig_throwsNotImplementedException (line 352) | @Test
FILE: plugin/src/test/java/com/google/tsunami/plugin/payload/PayloadSecretGeneratorTest.java
class PayloadSecretGeneratorTest (line 27) | @RunWith(JUnit4.class)
method nextBytes (line 31) | @Override
method generate_always_generatesExpectedSecretString (line 37) | @Test
FILE: plugin/src/test/java/com/google/tsunami/plugin/payload/PayloadTest.java
class PayloadTest (line 30) | @RunWith(JUnit4.class)
method getPayload_returnsPayloadString (line 37) | @Test
method checkIfExecuted_withNoParameter_executesValidator (line 45) | @Test
method checkIfExecuted_withString_executesValidator (line 54) | @Test
method checkIfExecuted_withByteString_executesValidator (line 63) | @Test
method checkIfExecuted_withOptional_executesValidator (line 72) | @Test
method getPayloadAttributes_returnsPayloadAttributes (line 81) | @Test
class TestValidatorIsCalledValidator (line 89) | private static final class TestValidatorIsCalledValidator implements V...
method isExecuted (line 92) | @Override
FILE: plugin_server/py/common/data/network_endpoint_utils.py
function has_ip_address (line 38) | def has_ip_address(network_endpoint: NetworkEndpoint) -> bool:
function has_hostname (line 42) | def has_hostname(network_endpoint: NetworkEndpoint) -> bool:
function has_port (line 46) | def has_port(network_endpoint: NetworkEndpoint) -> bool:
function is_ipv6_endpoint (line 50) | def is_ipv6_endpoint(network_endpoint: NetworkEndpoint) -> bool:
function to_uri_authority (line 56) | def to_uri_authority(network_endpoint: NetworkEndpoint) -> str:
function for_ip (line 99) | def for_ip(ip_address: str) -> NetworkEndpoint:
function for_ip_and_port (line 106) | def for_ip_and_port(ip_address: str, port: int) -> NetworkEndpoint:
function for_hostname (line 115) | def for_hostname(hostname: str) -> NetworkEndpoint:
function for_ip_and_hostname (line 124) | def for_ip_and_hostname(ip_address: str, hostname: str) -> NetworkEndpoint:
function for_hostname_and_port (line 132) | def for_hostname_and_port(hostname: str, port: int) -> NetworkEndpoint:
function for_ip_hostname_and_port (line 143) | def for_ip_hostname_and_port(ip_address: str, hostname: str,
function for_network_endpoint_and_port (line 154) | def for_network_endpoint_and_port(network_endpoint: NetworkEndpoint,
function create_with_ip (line 170) | def create_with_ip(ip_address: str) -> NetworkEndpoint:
function validate_port (line 182) | def validate_port(port: int) -> None:
function validate_hostname (line 187) | def validate_hostname(hostname: str) -> None:
function raise_invalid_network_endpoint_type (line 195) | def raise_invalid_network_endpoint_type(endpoint_type: Type) -> None:
function address_family (line 200) | def address_family(ip_address: str) -> AddressFamily:
function ip_to_uri (line 208) | def ip_to_uri(ip_address: str) -> str:
FILE: plugin_server/py/common/data/network_endpoint_utils_test.py
function _make_ipv4_endpoint (line 19) | def _make_ipv4_endpoint(port=False):
function _make_ipv6_endpoint (line 26) | def _make_ipv6_endpoint(port=False):
function _make_hostname_endpoint (line 33) | def _make_hostname_endpoint(port=False):
function _add_network_type_and_port (line 45) | def _add_network_type_and_port(network_endpoint, port=False):
class NetworkEndpointUtilsTest (line 54) | class NetworkEndpointUtilsTest(parameterized.TestCase):
method test_has_hostname (line 55) | def test_has_hostname(self):
method test_has_port (line 66) | def test_has_port(self):
method test_is_ipv6_endpoint (line 78) | def test_is_ipv6_endpoint(self, network_endpoint: NetworkEndpoint):
method test_is_ipv6_endpoint_returns_false (line 86) | def test_is_ipv6_endpoint_returns_false(self,
method test_to_uri_authority (line 100) | def test_to_uri_authority(self, network_endpoint: NetworkEndpoint,
method test_to_uri_authority_ip_and_host (line 113) | def test_to_uri_authority_ip_and_host(self, network_endpoint: NetworkE...
method test_to_uri_authority_ip_and_host_with_unspecified_type (line 121) | def test_to_uri_authority_ip_and_host_with_unspecified_type(self):
method test_for_ip_with_ipv4 (line 130) | def test_for_ip_with_ipv4(self):
method test_for_ip_with_ipv6 (line 134) | def test_for_ip_with_ipv6(self):
method test_for_ip_and_port_with_ipv4_and_port (line 138) | def test_for_ip_and_port_with_ipv4_and_port(self):
method test_for_ip_and_port_with_ipv6_and_port (line 142) | def test_for_ip_and_port_with_ipv6_and_port(self):
method test_for_hostname_with_hostname (line 146) | def test_for_hostname_with_hostname(self):
method test_for_hostname_and_port_with_hostname_and_port (line 151) | def test_for_hostname_and_port_with_hostname_and_port(self):
method test_for_ip_and_hostname_with_ipv4_and_hostname (line 157) | def test_for_ip_and_hostname_with_ipv4_and_hostname(self):
method test_for_ip_and_hostname_with_ipv6_and_hostname (line 165) | def test_for_ip_and_hostname_with_ipv6_and_hostname(self):
method test_for_ip_hostname_and_port_with_ipv4_hostname_and_port (line 173) | def test_for_ip_hostname_and_port_with_ipv4_hostname_and_port(self):
method test_for_ip_hostname_and_port_with_ipv6_hostname_and_port (line 182) | def test_for_ip_hostname_and_port_with_ipv6_hostname_and_port(self):
method test_for_ip_hostname_and_port_with_invalid_port (line 191) | def test_for_ip_hostname_and_port_with_invalid_port(self):
method test_for_network_endpoint_and_port_with_ipv4_and_port (line 197) | def test_for_network_endpoint_and_port_with_ipv4_and_port(self):
method test_for_network_endpoint_and_port_with_ipv6_and_port (line 204) | def test_for_network_endpoint_and_port_with_ipv6_and_port(self):
method test_for_network_endpoint_and_port_with_hostname_and_port (line 211) | def test_for_network_endpoint_and_port_with_hostname_and_port(self):
method test_for_network_endpoint_and_port_with_ip_and_port (line 218) | def test_for_network_endpoint_and_port_with_ip_and_port(self):
method test_for_ip_with_invalid_ip (line 231) | def test_for_ip_with_invalid_ip(self):
method test_for_ip_and_port_with_invalid_ip (line 236) | def test_for_ip_and_port_with_invalid_ip(self):
method test_for_ip_and_port_with_invalid_port (line 241) | def test_for_ip_and_port_with_invalid_port(self):
method test_for_hostname_with_ip (line 251) | def test_for_hostname_with_ip(self):
method test_for_hostname_and_port_with_invalid_ip (line 261) | def test_for_hostname_and_port_with_invalid_ip(self):
method test_for_hostname_and_port_with_invalid_port (line 271) | def test_for_hostname_and_port_with_invalid_port(self):
method test_for_network_endpoint_and_port_with_invalid_endpoint_type (line 281) | def test_for_network_endpoint_and_port_with_invalid_endpoint_type(self):
method testfor_network_endpoint_and_port_with_invalid_port (line 293) | def testfor_network_endpoint_and_port_with_invalid_port(self):
FILE: plugin_server/py/common/data/network_service_utils.py
function is_web_service (line 38) | def is_web_service(network_service: NetworkService) -> bool:
function is_plain_http_service (line 43) | def is_plain_http_service(network_service: NetworkService) -> bool:
function get_service_name (line 49) | def get_service_name(network_service: NetworkService) -> str:
function build_uri_network_service (line 54) | def build_uri_network_service(uri_string: str) -> NetworkService:
function build_web_application_root_url (line 98) | def build_web_application_root_url(network_service: NetworkService) -> str:
function build_web_protocol (line 116) | def build_web_protocol(network_service: NetworkService) -> str:
function build_web_uri_authority (line 123) | def build_web_uri_authority(network_service: NetworkService) -> str:
function build_web_app_root_path (line 166) | def build_web_app_root_path(network_service: NetworkService) -> str:
function get_address_family (line 178) | def get_address_family(address_family: socket.AddressFamily) -> AddressF...
function sanitize_port (line 187) | def sanitize_port(port: Optional[int], scheme: str) -> int:
function get_port (line 193) | def get_port(port: int, scheme: str) -> int:
function validate_scheme (line 199) | def validate_scheme(scheme: str) -> None:
FILE: plugin_server/py/common/data/network_service_utils_test.py
class NetworkServiceUtilsTest (line 25) | class NetworkServiceUtilsTest(parameterized.TestCase):
method make_web_service (line 26) | def make_web_service(self, service_name: str):
method make_ip_port_endpoint (line 30) | def make_ip_port_endpoint(self, port: int = _PORT):
method make_web_service_context (line 39) | def make_web_service_context(self, root: str = _ROOT):
method test_is_web_service (line 52) | def test_is_web_service(self, service_name: str):
method test_is_web_service_with_invalid_web_service (line 56) | def test_is_web_service_with_invalid_web_service(self):
method test_is_plain_http_service (line 65) | def test_is_plain_http_service(self, service_name: str):
method test_is_plain_http_service_with_invalid_service (line 75) | def test_is_plain_http_service_with_invalid_service(self, service_name...
method test_get_service_name_with_software (line 80) | def test_get_service_name_with_software(self):
method test_get_service_name_with_web_service (line 87) | def test_get_service_name_with_web_service(self):
method test_build_web_application_root_url (line 102) | def test_build_web_application_root_url(self, service_name: str, port:...
method test_build_uri_network_service_with_ipv4 (line 112) | def test_build_uri_network_service_with_ipv4(self):
method test_build_uri_network_service_with_ipv6 (line 140) | def test_build_uri_network_service_with_ipv6(self):
method test_build_uri_network_service_with_port_number_zero (line 175) | def test_build_uri_network_service_with_port_number_zero(self):
method test_build_uri_network_service_with_invalid_scheme (line 195) | def test_build_uri_network_service_with_invalid_scheme(self):
FILE: plugin_server/py/common/net/http/host_resolver_http_adapter.py
class HostResolverHttpAdapter (line 12) | class HostResolverHttpAdapter(requests.adapters.HTTPAdapter):
method __init__ (line 27) | def __init__(self, pool_connections: int, pool_maxsize: int):
method _add_host_header (line 32) | def _add_host_header(
method _require_ipv6_brackets (line 38) | def _require_ipv6_brackets(self, ip: str) -> str:
method _resolve (line 46) | def _resolve(self,
method send (line 65) | def send(
FILE: plugin_server/py/common/net/http/host_resolver_http_adapter_test.py
class HostResolverHttpAdapterTest (line 14) | class HostResolverHttpAdapterTest(parameterized.TestCase):
method setUpClass (line 17) | def setUpClass(cls):
method setUp (line 21) | def setUp(self):
method test_send_dispatches_with_host_header (line 43) | def test_send_dispatches_with_host_header(self, host):
method test_send_without_target_ip_dispatches_default_hostname (line 54) | def test_send_without_target_ip_dispatches_default_hostname(self):
method test_send_when_hostname_resolves_to_ip_uses_default_hostname (line 63) | def test_send_when_hostname_resolves_to_ip_uses_default_hostname(self):
method test_send_when_hostname_is_the_ip_uses_default_hostname (line 77) | def test_send_when_hostname_is_the_ip_uses_default_hostname(self):
method test_send_when_hostname_is_case_insensitive (line 90) | def test_send_when_hostname_is_case_insensitive(self):
method test_send_when_hostname_does_not_resolve_to_ipv4_uses_ipv4 (line 103) | def test_send_when_hostname_does_not_resolve_to_ipv4_uses_ipv4(self):
method test_send_when_hostname_does_not_resolve_to_ipv6_uses_ipv6 (line 117) | def test_send_when_hostname_does_not_resolve_to_ipv6_uses_ipv6(self):
method _prepare_request (line 134) | def _prepare_request(self, url):
FILE: plugin_server/py/common/net/http/http_client.py
class HttpClient (line 10) | class HttpClient(metaclass=abc.ABCMeta):
method __init__ (line 23) | def __init__(self,
method get_log_id (line 34) | def get_log_id(self) -> str:
method send (line 38) | def send(self,
method send_async (line 45) | def send_async(
method modify (line 53) | def modify(self):
class Builder (line 58) | class Builder(metaclass=abc.ABCMeta):
method set_allow_redirects (line 62) | def set_allow_redirects(self, allow_redirects: bool):
method set_verify_ssl (line 66) | def set_verify_ssl(self, verify_ssl: bool):
method set_log_id (line 70) | def set_log_id(self, log_id: str):
method set_timeout_sec (line 74) | def set_timeout_sec(self, timeout_sec: float):
method build (line 78) | def build(self):
FILE: plugin_server/py/common/net/http/http_header_fields.py
class HttpHeaderFields (line 6) | class HttpHeaderFields(enum.Enum):
method list (line 187) | def list(cls):
method get_from_lower (line 191) | def get_from_lower(cls, name):
FILE: plugin_server/py/common/net/http/http_header_fields_test.py
class HttpHeaderFieldsTest (line 10) | class HttpHeaderFieldsTest(absltest.TestCase):
method test_list_returns_all_header_fields (line 11) | def test_list_returns_all_header_fields(self):
method test_get_from_lower_with_existing_field (line 14) | def test_get_from_lower_with_existing_field(self):
method test_get_from_lower_with_unknown_field (line 19) | def test_get_from_lower_with_unknown_field(self):
FILE: plugin_server/py/common/net/http/http_headers.py
class HttpHeaders (line 9) | class HttpHeaders:
method __init__ (line 19) | def __init__(self):
method names (line 22) | def names(self) -> set[str]:
method get (line 26) | def get(self, name: str) -> Optional[str]:
method get_all (line 33) | def get_all(self, name: str) -> list[str]:
method builder (line 53) | def builder(cls) -> 'Builder':
class Builder (line 57) | class Builder:
method __init__ (line 69) | def __init__(self):
method build (line 72) | def build(self) -> HttpHeaders:
method add_header (line 75) | def add_header(self, name: str, value: str, canonicalize: bool = True):
method _canonicalize_header_name (line 100) | def _canonicalize_header_name(self, name, value) -> str:
method _is_legal_header_name (line 107) | def _is_legal_header_name(self, name: str) -> bool:
method _is_legal_header_value (line 110) | def _is_legal_header_value(self, value: str) -> bool:
function _canonicalize (line 114) | def _canonicalize(header_name: str) -> str:
FILE: plugin_server/py/common/net/http/http_headers_test.py
class HttpHeadersTest (line 13) | class HttpHeadersTest(parameterized.TestCase):
method test_builder_add_header_always_puts_in_headers_map (line 14) | def test_builder_add_header_always_puts_in_headers_map(self):
method test_builder_add_header_with_known_header_canonicalizes_header_name (line 19) | def test_builder_add_header_with_known_header_canonicalizes_header_nam...
method test_builder_add_header_with_enabled_canonicalization (line 25) | def test_builder_add_header_with_enabled_canonicalization(self):
method test_builder_add_header_with_disabled_canonicalization_adds_raw_header (line 31) | def test_builder_add_header_with_disabled_canonicalization_adds_raw_he...
method test_builder_add_header_raises_error (line 46) | def test_builder_add_header_raises_error(self, field, value, message):
method test_names_always_returns_all_header_names (line 51) | def test_names_always_returns_all_header_names(self):
method test_get_when_requested_header_exists_returns_requested_header (line 61) | def test_get_when_requested_header_exists_returns_requested_header(self):
method test_get_when_multiple_values_exist_returns_first_value (line 69) | def test_get_when_multiple_values_exist_returns_first_value(self):
method test_get_when_requested_header_does_not_exist_returns_none (line 78) | def test_get_when_requested_header_does_not_exist_returns_none(self):
method test_get_with_none_header_name_raise_error (line 83) | def test_get_with_none_header_name_raise_error(self):
method test_get_all_always_returns_requested_values (line 90) | def test_get_all_always_returns_requested_values(self):
method test_get_all_with_known_header_value_canonicalizes_requested_header (line 99) | def test_get_all_with_known_header_value_canonicalizes_requested_heade...
method test_get_all_when_request_value_does_not_exist_returns_empty_list (line 108) | def test_get_all_when_request_value_does_not_exist_returns_empty_list(...
method test_get_all_with_none_header_name_raise_error (line 116) | def test_get_all_with_none_header_name_raise_error(self):
FILE: plugin_server/py/common/net/http/http_method.py
class HttpMethod (line 6) | class HttpMethod(str, enum.Enum):
method __init__ (line 18) | def __init__(self, string):
FILE: plugin_server/py/common/net/http/http_request.py
function check_url_argument (line 10) | def check_url_argument(func):
class HttpRequest (line 18) | class HttpRequest:
method __init__ (line 31) | def __init__(self):
method get (line 39) | def get(cls, url: str):
method head (line 44) | def head(cls, url: str):
method post (line 49) | def post(cls, url: str):
method put (line 54) | def put(cls, url: str):
method delete (line 59) | def delete(cls, url: str):
method builder (line 63) | def builder(cls):
class Builder (line 67) | class Builder:
method __init__ (line 74) | def __init__(self):
method set_method (line 77) | def set_method(self, method: HttpMethod) -> 'Builder':
method set_url (line 82) | def set_url(self, url: str) -> 'Builder':
method set_headers (line 87) | def set_headers(self, headers: HttpHeaders) -> 'Builder':
method set_request_body (line 92) | def set_request_body(self, request_body: Optional[bytes] = None) -> 'B...
method with_empty_headers (line 97) | def with_empty_headers(self) -> 'Builder':
method build (line 102) | def build(self) -> 'HttpRequest':
FILE: plugin_server/py/common/net/http/http_request_test.py
class HttpRequestTest (line 11) | class HttpRequestTest(parameterized.TestCase):
method test_http_request_methods_with_empty_url_raise_error (line 16) | def test_http_request_methods_with_empty_url_raise_error(
method test_get_builds_http_get_request (line 22) | def test_get_builds_http_get_request(self):
method test_head_builds_http_head_request (line 28) | def test_head_builds_http_head_request(self):
method test_head_builds_http_post_request (line 34) | def test_head_builds_http_post_request(self):
method test_head_builds_http_delete_request (line 40) | def test_head_builds_http_delete_request(self):
method test_put_builds_http_put_request (line 46) | def test_put_builds_http_put_request(self):
method test_get_with_request_body_raise_error (line 52) | def test_get_with_request_body_raise_error(self):
FILE: plugin_server/py/common/net/http/http_response.py
class HttpResponse (line 11) | class HttpResponse(metaclass=abc.ABCMeta):
method __init__ (line 23) | def __init__(self):
method body_string (line 29) | def body_string(self) -> str:
method body_json (line 35) | def body_json(self) -> Mapping[str, Any] | None:
method json_field_has_value (line 42) | def json_field_has_value(self, field: str, value: str):
method builder (line 50) | def builder(cls):
class Builder (line 54) | class Builder:
method __init__ (line 61) | def __init__(self):
method set_status (line 64) | def set_status(self, status: HttpStatus):
method set_headers (line 69) | def set_headers(self, headers: HttpHeaders):
method set_response_body (line 74) | def set_response_body(self, response_body: bytes | None):
method set_url (line 79) | def set_url(self, url: str):
method build (line 84) | def build(self):
FILE: plugin_server/py/common/net/http/http_response_test.py
class HttpResponseTest (line 10) | class HttpResponseTest(absltest.TestCase):
method test_body_json_with_valid_response_body_returns_parsed_json (line 11) | def test_body_json_with_valid_response_body_returns_parsed_json(self):
method test_body_json_with_no_response_body_returns_null (line 20) | def test_body_json_with_no_response_body_returns_null(self):
method test_body_json_with_non_json_response_body_returns_null (line 25) | def test_body_json_with_non_json_response_body_returns_null(self):
method test_json_field_has_value_with_empty_json_body_returns_false (line 31) | def test_json_field_has_value_with_empty_json_body_returns_false(self):
method test_json_field_has_value_with_no_body_returns_false (line 37) | def test_json_field_has_value_with_no_body_returns_false(self):
method test_json_field_has_value_with_non_empty_json_body_returns_true (line 42) | def test_json_field_has_value_with_non_empty_json_body_returns_true(se...
method test_is_success_with_unspecified_status_returns_false (line 49) | def test_is_success_with_unspecified_status_returns_false(self):
FILE: plugin_server/py/common/net/http/http_status.py
class HttpStatus (line 6) | class HttpStatus(enum.MultiValueEnum):
method from_code (line 93) | def from_code(cls, code: int):
method __init__ (line 109) | def __init__(self, code, message=""):
method __str__ (line 113) | def __str__(self) -> str:
method is_redirect (line 116) | def is_redirect(self) -> bool:
method is_success (line 119) | def is_success(self) -> bool:
FILE: plugin_server/py/common/net/http/http_status_test.py
class HttpStatusTest (line 10) | class HttpStatusTest(parameterized.TestCase):
method test_from_code_with_status_code_returns_http_status (line 11) | def test_from_code_with_status_code_returns_http_status(self):
method test_from_code_with_invalid_status_code_returns_http_status_unspecified (line 15) | def test_from_code_with_invalid_status_code_returns_http_status_unspec...
method test_is_redirect_returns_true (line 27) | def test_is_redirect_returns_true(self, status):
method test_is_redirect_with_non_redirected_status_returns_false (line 30) | def test_is_redirect_with_non_redirected_status_returns_false(self):
method test_is_success_with_code_between_199_and_300 (line 33) | def test_is_success_with_code_between_199_and_300(self):
method test___str__returns_status_message (line 38) | def test___str__returns_status_message(self):
FILE: plugin_server/py/common/net/http/requests_http_client.py
class RequestsHttpClient (line 30) | class RequestsHttpClient(HttpClient):
method __init__ (line 46) | def __init__(
method get_log_id (line 62) | def get_log_id(self) -> str:
method send (line 65) | def send(self,
method send_async (line 81) | def send_async(
method modify (line 96) | def modify(cls):
method _build_response_headers (line 100) | def _build_response_headers(self, headers: dict[str, str]) -> HttpHead...
method _parse_response (line 106) | def _parse_response(self, res: requests.Response) -> HttpResponse:
method _prepare_future (line 118) | async def _prepare_future(
method _prepare_request (line 138) | def _prepare_request(
method _serialize_request_headers (line 164) | def _serialize_request_headers(self, headers: HttpHeaders) -> dict[str...
method _get_ip (line 173) | def _get_ip(self, network_service: Optional[NetworkService]) -> Option...
class RequestsHttpClientBuilder (line 179) | class RequestsHttpClientBuilder(Builder):
method __init__ (line 182) | def __init__(self):
method set_allow_redirects (line 197) | def set_allow_redirects(
method set_log_id (line 203) | def set_log_id(self, log_id: str) -> 'RequestsHttpClientBuilder':
method set_max_workers (line 207) | def set_max_workers(self, max_workers: int) -> 'RequestsHttpClientBuil...
method set_pool_connections (line 211) | def set_pool_connections(
method set_pool_maxsize (line 217) | def set_pool_maxsize(self, pool_maxsize: int) -> 'RequestsHttpClientBu...
method set_timeout_sec (line 221) | def set_timeout_sec(self, timeout_sec: float) -> 'RequestsHttpClientBu...
method set_verify_ssl (line 225) | def set_verify_ssl(self, verify_ssl: bool) -> 'RequestsHttpClientBuild...
method build (line 229) | def build(self) -> RequestsHttpClient:
FILE: plugin_server/py/common/net/http/requests_http_client_test.py
class RequestsHttpClientTest (line 23) | class RequestsHttpClientTest(absltest.TestCase):
method setUpClass (line 25) | def setUpClass(cls):
method test_get_log_id (line 29) | def test_get_log_id(self):
method test_send_returns_expected_http_response (line 33) | def test_send_returns_expected_http_response(self, mock):
method test_send_with_get_request_returns_expected_http_response (line 45) | def test_send_with_get_request_returns_expected_http_response(self, mo...
method test_send_async_with_get_request_returns_expected_http_response (line 63) | def test_send_async_with_get_request_returns_expected_http_response(
method test_send_with_head_request_returns_http_response_without_body (line 83) | def test_send_with_head_request_returns_http_response_without_body(
method test_send_async_with_head_request_returns_expected_http_response_without_body (line 103) | def test_send_async_with_head_request_returns_expected_http_response_w...
method test_send_with_post_request_returns_expected_http_response (line 123) | def test_send_with_post_request_returns_expected_http_response(
method test_send_async_with_post_request_returns_expected_http_response (line 148) | def test_send_async_with_post_request_returns_expected_http_response(
method test_send_with_post_request_with_empty_headers_returns_expected_http_response (line 173) | def test_send_with_post_request_with_empty_headers_returns_expected_ht...
method test_send_async_with_post_request_with_empty_headers_returns_expected_http_response (line 193) | def test_send_async_with_post_request_with_empty_headers_returns_expec...
method test_send_with_hostname_and_ip_use_hostname_as_proxy (line 212) | def test_send_with_hostname_and_ip_use_hostname_as_proxy(self, mock):
method test_send_async_with_hostname_and_ip_use_hostname_as_proxy (line 237) | def test_send_async_with_hostname_and_ip_use_hostname_as_proxy(self, m...
method test_requests_http_client_default_configs (line 261) | def test_requests_http_client_default_configs(self):
method test_send_with_modified_configuration (line 266) | def test_send_with_modified_configuration(self, mock):
method test_send_when_request_failed_raise_error (line 298) | def test_send_when_request_failed_raise_error(self):
method test_send_async_when_request_failed_raise_error (line 305) | def test_send_async_when_request_failed_raise_error(self):
method test__serialize_request_headers_include_custom_user_agent (line 312) | def test__serialize_request_headers_include_custom_user_agent(self):
method _assert_response_is_expected (line 324) | def _assert_response_is_expected(self, response, expected):
method _create_expected_response (line 330) | def _create_expected_response(
FILE: plugin_server/py/plugin/payload/payload.py
class Payload (line 11) | class Payload:
method __init__ (line 14) | def __init__(
method get_payload (line 26) | def get_payload(self) -> str:
method check_if_executed (line 40) | def check_if_executed(
method get_payload_attributes (line 59) | def get_payload_attributes(self) -> payload_generator_pb2.PayloadAttri...
FILE: plugin_server/py/plugin/payload/payload_generator.py
class PayloadGenerator (line 13) | class PayloadGenerator:
method __init__ (line 20) | def __init__(
method is_callback_server_enabled (line 38) | def is_callback_server_enabled(self):
method generate (line 46) | def generate(self, config: pg.PayloadGeneratorConfig) -> Payload:
method generate_no_callback (line 61) | def generate_no_callback(self, config: pg.PayloadGeneratorConfig) -> P...
method _generate_payload (line 73) | def _generate_payload(
method _find_matching_payload (line 100) | def _find_matching_payload(
method _parse_payload (line 107) | def _parse_payload(
method _payload_matches_config (line 155) | def _payload_matches_config(
function _is_executed (line 170) | def _is_executed(regex: str) -> Callable[[Any, Optional[bytes]], bool]:
FILE: plugin_server/py/plugin/payload/payload_generator_test.py
class PayloadGeneratorWithCallbackTest (line 29) | class PayloadGeneratorWithCallbackTest(parameterized.TestCase):
method setUpClass (line 32) | def setUpClass(cls):
method test_is_callback_server_enabled_returns_true (line 42) | def test_is_callback_server_enabled_returns_true(self):
method test_generate_with_callback_returns_payload (line 53) | def test_generate_with_callback_returns_payload(
method test_generate_no_callback_returns_payload (line 85) | def test_generate_no_callback_returns_payload(
method test_check_if_executed_linux_and_payload_exec_returns_true (line 93) | def test_check_if_executed_linux_and_payload_exec_returns_true(self, m...
method test_check_if_executed_linux_and_payload_exec_with_dns_returns_true (line 100) | def test_check_if_executed_linux_and_payload_exec_with_dns_returns_true(
method test_check_if_executed_linux_no_payload_exec_returns_false (line 108) | def test_check_if_executed_linux_no_payload_exec_returns_false(self, m...
method test_check_if_executed_ssrf_and_payload_exec_returns_true (line 115) | def test_check_if_executed_ssrf_and_payload_exec_returns_true(self, mo...
method test_check_if_executed_ssrf_and_no_payload_exec_returns_false (line 122) | def test_check_if_executed_ssrf_and_no_payload_exec_returns_false(self...
method test_generate_with_no_vulnerability_type_raises_lookup_error (line 128) | def test_generate_with_no_vulnerability_type_raises_lookup_error(self):
method test_generate_with_no_interpretation_environment_raises_error (line 146) | def test_generate_with_no_interpretation_environment_raises_error(self):
method test_generate_with_no_execution_environment_raises_lookup_error (line 164) | def test_generate_with_no_execution_environment_raises_lookup_error(se...
method test_generate_with_no_config_raises_lookup_error (line 181) | def test_generate_with_no_config_raises_lookup_error(self):
class PayloadGeneratorWithoutCallbackTest (line 195) | class PayloadGeneratorWithoutCallbackTest(parameterized.TestCase):
method setUpClass (line 198) | def setUpClass(cls):
method test_is_callback_server_enabled_with_no_callback_returns_false (line 208) | def test_is_callback_server_enabled_with_no_callback_returns_false(self):
method test_generate_without_callback_returns_payload (line 236) | def test_generate_without_callback_returns_payload(
method test_check_if_executed_with_correct_payload_input_returns_true (line 260) | def test_check_if_executed_with_correct_payload_input_returns_true(
method test_check_if_executed_with_bad_payload_input_returns_false (line 276) | def test_check_if_executed_with_bad_payload_input_returns_false(
method test_generate_with_no_callback_no_vulnerability_type_raises_error (line 283) | def test_generate_with_no_callback_no_vulnerability_type_raises_error(...
method test_generate_with_no_callback_no_interpretation_env_raises_error (line 301) | def test_generate_with_no_callback_no_interpretation_env_raises_error(...
method test_generate_with_no_callback_and_no_execution_env_raises_error (line 319) | def test_generate_with_no_callback_and_no_execution_env_raises_error(s...
method test_generate_with_no_callback_and_no_config_raises_lookup_error (line 336) | def test_generate_with_no_callback_and_no_config_raises_lookup_error(s...
method test_generate_with_no_callback_and_no_validation_type_raises_error (line 351) | def test_generate_with_no_callback_and_no_validation_type_raises_error...
method test_check_if_executed_with_no_callback_and_no_payload_raises_error (line 377) | def test_check_if_executed_with_no_callback_and_no_payload_raises_erro...
FILE: plugin_server/py/plugin/payload/payload_secret_generator.py
class PayloadSecretGenerator (line 7) | class PayloadSecretGenerator:
method generate (line 10) | def generate(self, size: int) -> str:
FILE: plugin_server/py/plugin/payload/payload_secret_generator_test.py
class PayloadSecretGeneratorTest (line 12) | class PayloadSecretGeneratorTest(googletest.TestCase):
method test_generate_returns_secret_with_specified_size (line 14) | def test_generate_returns_secret_with_specified_size(self):
FILE: plugin_server/py/plugin/payload/payload_test.py
class PayloadTest (line 15) | class PayloadTest(parameterized.TestCase):
class MockValidator (line 17) | class MockValidator(Validator):
method is_executed (line 20) | def is_executed(self, payload_data: Optional[bytes]):
method test_get_payload_returns_payload_string (line 24) | def test_get_payload_returns_payload_string(self):
method test_check_if_executed (line 35) | def test_check_if_executed(self, param):
method test_get_payload_attributes_returns_payload_attributes (line 41) | def test_get_payload_attributes_returns_payload_attributes(self):
FILE: plugin_server/py/plugin/payload/payload_utility.py
function set_payload_file_path (line 11) | def set_payload_file_path(path: str):
function get_parsed_payload (line 24) | def get_parsed_payload() -> list[pg.PayloadDefinition]:
function _validate_payloads (line 47) | def _validate_payloads(
FILE: plugin_server/py/plugin/payload/payload_utility_test.py
class PayloadUtilityTest (line 10) | class PayloadUtilityTest(googletest.TestCase):
method test_get_parsed_payload_with_good_payloads_returns_payloads (line 12) | def test_get_parsed_payload_with_good_payloads_returns_payloads(self):
method test_get_parsed_payload_without_name_raise_valueerror (line 25) | def test_get_parsed_payload_without_name_raise_valueerror(self):
method test_get_parsed_payload_no_interpretation_environment_raise_error (line 39) | def test_get_parsed_payload_no_interpretation_environment_raise_error(...
method test_get_parsed_payload_no_execution_environment_raise_error (line 57) | def test_get_parsed_payload_no_execution_environment_raise_error(self):
method test_get_parsed_payload_no_vulnerability_type_raise_error (line 75) | def test_get_parsed_payload_no_vulnerability_type_raise_error(self):
method test_get_parsed_payload_no_payload_string_raise_error (line 93) | def test_get_parsed_payload_no_payload_string_raise_error(self):
method test_get_parsed_payload_no_callback_constant_in_payload_raise_error (line 110) | def test_get_parsed_payload_no_callback_constant_in_payload_raise_erro...
method test_get_parsed_payload_no_callback_server_no_validation_type_raise_error (line 131) | def test_get_parsed_payload_no_callback_server_no_validation_type_rais...
method test_get_parsed_payload_no_callback_server_no_val_regex_raise_error (line 154) | def test_get_parsed_payload_no_callback_server_no_val_regex_raise_error(
FILE: plugin_server/py/plugin/payload/validator.py
class Validator (line 7) | class Validator(metaclass=abc.ABCMeta):
method is_executed (line 11) | def is_executed(self, data: Optional[bytes]) -> bool:
FILE: plugin_server/py/plugin/tcs_client.py
class TcsClient (line 14) | class TcsClient:
method __init__ (line 17) | def __init__(
method is_callback_server_enabled (line 38) | def is_callback_server_enabled(self) -> bool:
method get_callback_uri (line 49) | def get_callback_uri(self, secret_string: str) -> str:
method has_oob_log (line 76) | def has_oob_log(self, secret_string: str) -> bool:
method _send_polling_request (line 91) | def _send_polling_request(
method _build_polling_request (line 118) | def _build_polling_request(self, secret_string: str) -> HttpRequest:
method _create_callback_address (line 130) | def _create_callback_address(
method _remove_trailing_slashes (line 146) | def _remove_trailing_slashes(self, url: str) -> str:
FILE: plugin_server/py/plugin/tcs_client_test.py
class TcsClientTest (line 20) | class TcsClientTest(parameterized.TestCase):
method setUpClass (line 23) | def setUpClass(cls):
method test_get_callback_uri (line 60) | def test_get_callback_uri(self, address, port, exepected_uri):
method test_is_callback_server_enabled (line 72) | def test_is_callback_server_enabled(
method test_tcs_client_with_invalid_port_raises_error (line 78) | def test_tcs_client_with_invalid_port_raises_error(self):
method test_has_oob_log_sends_polling_request (line 83) | def test_has_oob_log_sends_polling_request(self, mock):
method test_has_oob_log_with_no_logs_returns_false (line 92) | def test_has_oob_log_with_no_logs_returns_false(self, mock):
method test_has_oob_log_with_no_response_returns_false (line 101) | def test_has_oob_log_with_no_response_returns_false(self, mock):
method test_has_oob_log_with_unsuccessful_response_returns_false (line 107) | def test_has_oob_log_with_unsuccessful_response_returns_false(self, mo...
method test_create_tscclient_removes_trailing_slashes (line 112) | def test_create_tscclient_removes_trailing_slashes(self):
FILE: plugin_server/py/plugin_server.py
function main (line 78) | def main(unused_argv):
function _import_py_plugins (line 114) | def _import_py_plugins(plugin_pkg: types.ModuleType):
function _configure_log (line 125) | def _configure_log():
function _configure_plugin_service (line 139) | def _configure_plugin_service(server):
function _register_health_service (line 171) | def _register_health_service(server):
function _set_health_service_to_serving (line 181) | def _set_health_service_to_serving(server, health_servicer):
FILE: plugin_server/py/plugin_service.py
class PluginServiceServicer (line 36) | class PluginServiceServicer(plugin_service_pb2_grpc.PluginServiceServicer):
method __init__ (line 43) | def __init__(self, py_plugins: list[tsunami_plugin.TsunamiPlugin],
method Run (line 48) | def Run(
method ListPlugins (line 79) | def ListPlugins(
FILE: plugin_server/py/plugin_service_test.py
class PluginServiceTest (line 53) | class PluginServiceTest(absltest.TestCase):
method setUp (line 55) | def setUp(self):
method tearDown (line 83) | def tearDown(self):
method test_run_plugins_registered_returns_valid_response (line 87) | def test_run_plugins_registered_returns_valid_response(self):
method test_run_no_plugins_registered_returns_empty_response (line 119) | def test_run_no_plugins_registered_returns_empty_response(self):
method test_list_plugins_plugins_registered_returns_valid_response (line 129) | def test_list_plugins_plugins_registered_returns_valid_response(self):
function _build_network_endpoint (line 141) | def _build_network_endpoint(ip: str, port: int) -> _NetworkEndpoint:
function _get_address_family (line 149) | def _get_address_family(ip: str) -> _AddressFamily:
class FakeVulnDetector (line 159) | class FakeVulnDetector(tsunami_plugin.VulnDetector):
method __init__ (line 162) | def __init__(
method GetAdvisories (line 170) | def GetAdvisories(self) -> list[vulnerability_pb2.Vulnerability]:
method GetPluginDefinition (line 183) | def GetPluginDefinition(self):
method Detect (line 201) | def Detect(self, target, matched_services):
method _BuildFakeDetectionReport (line 208) | def _BuildFakeDetectionReport(self, target, network_service):
FILE: plugin_server/py/tsunami_plugin.py
class TsunamiPlugin (line 28) | class TsunamiPlugin(metaclass=abc.ABCMeta):
method GetPluginDefinition (line 31) | def GetPluginDefinition(self) -> PluginDefinition:
method __subclasshook__ (line 35) | def __subclasshook__(cls, subclass: abc.ABCMeta) -> bool:
class VulnDetector (line 41) | class VulnDetector(TsunamiPlugin):
method __init_subclass__ (line 50) | def __init_subclass__(cls, **kwargs):
method GetAdvisories (line 54) | def GetAdvisories(self) -> list[vulnerability_pb2.Vulnerability]:
method Detect (line 58) | def Detect(
FILE: proto/go/detection_go_proto/detection.pb.go
constant _ (line 39) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 41) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type DetectionStatus (line 45) | type DetectionStatus
method Enum (line 76) | func (x DetectionStatus) Enum() *DetectionStatus {
method String (line 82) | func (x DetectionStatus) String() string {
method Descriptor (line 86) | func (DetectionStatus) Descriptor() protoreflect.EnumDescriptor {
method Type (line 90) | func (DetectionStatus) Type() protoreflect.EnumType {
method Number (line 94) | func (x DetectionStatus) Number() protoreflect.EnumNumber {
constant DetectionStatus_DETECTION_STATUS_UNSPECIFIED (line 49) | DetectionStatus_DETECTION_STATUS_UNSPECIFIED DetectionStatus = 0
constant DetectionStatus_SAFE (line 51) | DetectionStatus_SAFE DetectionStatus = 1
constant DetectionStatus_VULNERABILITY_PRESENT (line 54) | DetectionStatus_VULNERABILITY_PRESENT DetectionStatus = 2
constant DetectionStatus_VULNERABILITY_VERIFIED (line 57) | DetectionStatus_VULNERABILITY_VERIFIED DetectionStatus = 3
type DetectionReport (line 99) | type DetectionReport struct
method Reset (line 110) | func (x *DetectionReport) Reset() {
method String (line 117) | func (x *DetectionReport) String() string {
method ProtoMessage (line 121) | func (*DetectionReport) ProtoMessage() {}
method ProtoReflect (line 123) | func (x *DetectionReport) ProtoReflect() protoreflect.Message {
method GetTargetInfo (line 135) | func (x *DetectionReport) GetTargetInfo() *reconnaissance_go_proto.Tar...
method GetNetworkService (line 142) | func (x *DetectionReport) GetNetworkService() *network_service_go_prot...
method GetDetectionTimestamp (line 149) | func (x *DetectionReport) GetDetectionTimestamp() *timestamppb.Timesta...
method GetDetectionStatus (line 156) | func (x *DetectionReport) GetDetectionStatus() DetectionStatus {
method GetVulnerability (line 163) | func (x *DetectionReport) GetVulnerability() *vulnerability_go_proto.V...
method SetTargetInfo (line 170) | func (x *DetectionReport) SetTargetInfo(v *reconnaissance_go_proto.Tar...
method SetNetworkService (line 174) | func (x *DetectionReport) SetNetworkService(v *network_service_go_prot...
method SetDetectionTimestamp (line 178) | func (x *DetectionReport) SetDetectionTimestamp(v *timestamppb.Timesta...
method SetDetectionStatus (line 182) | func (x *DetectionReport) SetDetectionStatus(v DetectionStatus) {
method SetVulnerability (line 186) | func (x *DetectionReport) SetVulnerability(v *vulnerability_go_proto.V...
method HasTargetInfo (line 190) | func (x *DetectionReport) HasTargetInfo() bool {
method HasNetworkService (line 197) | func (x *DetectionReport) HasNetworkService() bool {
method HasDetectionTimestamp (line 204) | func (x *DetectionReport) HasDetectionTimestamp() bool {
method HasVulnerability (line 211) | func (x *DetectionReport) HasVulnerability() bool {
method ClearTargetInfo (line 218) | func (x *DetectionReport) ClearTargetInfo() {
method ClearNetworkService (line 222) | func (x *DetectionReport) ClearNetworkService() {
method ClearDetectionTimestamp (line 226) | func (x *DetectionReport) ClearDetectionTimestamp() {
method ClearVulnerability (line 230) | func (x *DetectionReport) ClearVulnerability() {
type DetectionReport_builder (line 234) | type DetectionReport_builder struct
method Build (line 249) | func (b0 DetectionReport_builder) Build() *DetectionReport {
type DetectionReportList (line 261) | type DetectionReportList struct
method Reset (line 268) | func (x *DetectionReportList) Reset() {
method String (line 275) | func (x *DetectionReportList) String() string {
method ProtoMessage (line 279) | func (*DetectionReportList) ProtoMessage() {}
method ProtoReflect (line 281) | func (x *DetectionReportList) ProtoReflect() protoreflect.Message {
method GetDetectionReports (line 293) | func (x *DetectionReportList) GetDetectionReports() []*DetectionReport {
method SetDetectionReports (line 302) | func (x *DetectionReportList) SetDetectionReports(v []*DetectionReport) {
type DetectionReportList_builder (line 306) | type DetectionReportList_builder struct
method Build (line 312) | func (b0 DetectionReportList_builder) Build() *DetectionReportList {
constant file_detection_proto_rawDesc (line 322) | file_detection_proto_rawDesc = "" +
function init (line 366) | func init() { file_detection_proto_init() }
function file_detection_proto_init (line 367) | func file_detection_proto_init() {
FILE: proto/go/network_go_proto/network.pb.go
constant _ (line 35) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 37) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type AddressFamily (line 41) | type AddressFamily
method Enum (line 63) | func (x AddressFamily) Enum() *AddressFamily {
method String (line 69) | func (x AddressFamily) String() string {
method Descriptor (line 73) | func (AddressFamily) Descriptor() protoreflect.EnumDescriptor {
method Type (line 77) | func (AddressFamily) Type() protoreflect.EnumType {
method Number (line 81) | func (x AddressFamily) Number() protoreflect.EnumNumber {
constant AddressFamily_ADDRESS_FAMILY_UNSPECIFIED (line 44) | AddressFamily_ADDRESS_FAMILY_UNSPECIFIED AddressFamily = 0
constant AddressFamily_IPV4 (line 45) | AddressFamily_IPV4 AddressFamily = 4
constant AddressFamily_IPV6 (line 46) | AddressFamily_IPV6 AddressFamily = 6
type TransportProtocol (line 86) | type TransportProtocol
method Enum (line 111) | func (x TransportProtocol) Enum() *TransportProtocol {
method String (line 117) | func (x TransportProtocol) String() string {
method Descriptor (line 121) | func (TransportProtocol) Descriptor() protoreflect.EnumDescriptor {
method Type (line 125) | func (TransportProtocol) Type() protoreflect.EnumType {
method Number (line 129) | func (x TransportProtocol) Number() protoreflect.EnumNumber {
constant TransportProtocol_TRANSPORT_PROTOCOL_UNSPECIFIED (line 89) | TransportProtocol_TRANSPORT_PROTOCOL_UNSPECIFIED TransportProtocol = 0
constant TransportProtocol_TCP (line 90) | TransportProtocol_TCP TransportProtocol = 1
constant TransportProtocol_UDP (line 91) | TransportProtocol_UDP TransportProtocol = 2
constant TransportProtocol_SCTP (line 92) | TransportProtocol_SCTP TransportProtocol = 3
type NetworkEndpoint_Type (line 133) | type NetworkEndpoint_Type
method Enum (line 173) | func (x NetworkEndpoint_Type) Enum() *NetworkEndpoint_Type {
method String (line 179) | func (x NetworkEndpoint_Type) String() string {
method Descriptor (line 183) | func (NetworkEndpoint_Type) Descriptor() protoreflect.EnumDescriptor {
method Type (line 187) | func (NetworkEndpoint_Type) Type() protoreflect.EnumType {
method Number (line 191) | func (x NetworkEndpoint_Type) Number() protoreflect.EnumNumber {
constant NetworkEndpoint_TYPE_UNSPECIFIED (line 136) | NetworkEndpoint_TYPE_UNSPECIFIED NetworkEndpoint_Type = 0
constant NetworkEndpoint_IP (line 138) | NetworkEndpoint_IP NetworkEndpoint_Type = 1
constant NetworkEndpoint_IP_PORT (line 140) | NetworkEndpoint_IP_PORT NetworkEndpoint_Type = 2
constant NetworkEndpoint_HOSTNAME (line 142) | NetworkEndpoint_HOSTNAME NetworkEndpoint_Type = 3
constant NetworkEndpoint_HOSTNAME_PORT (line 144) | NetworkEndpoint_HOSTNAME_PORT NetworkEndpoint_Type = 4
constant NetworkEndpoint_IP_HOSTNAME (line 146) | NetworkEndpoint_IP_HOSTNAME NetworkEndpoint_Type = 5
constant NetworkEndpoint_IP_HOSTNAME_PORT (line 148) | NetworkEndpoint_IP_HOSTNAME_PORT NetworkEndpoint_Type = 6
type IpAddress (line 196) | type IpAddress struct
method Reset (line 204) | func (x *IpAddress) Reset() {
method String (line 211) | func (x *IpAddress) String() string {
method ProtoMessage (line 215) | func (*IpAddress) ProtoMessage() {}
method ProtoReflect (line 217) | func (x *IpAddress) ProtoReflect() protoreflect.Message {
method GetAddressFamily (line 229) | func (x *IpAddress) GetAddressFamily() AddressFamily {
method GetAddress (line 236) | func (x *IpAddress) GetAddress() string {
method SetAddressFamily (line 243) | func (x *IpAddress) SetAddressFamily(v AddressFamily) {
method SetAddress (line 247) | func (x *IpAddress) SetAddress(v string) {
type IpAddress_builder (line 251) | type IpAddress_builder struct
method Build (line 261) | func (b0 IpAddress_builder) Build() *IpAddress {
type Port (line 271) | type Port struct
method Reset (line 278) | func (x *Port) Reset() {
method String (line 285) | func (x *Port) String() string {
method ProtoMessage (line 289) | func (*Port) ProtoMessage() {}
method ProtoReflect (line 291) | func (x *Port) ProtoReflect() protoreflect.Message {
method GetPortNumber (line 303) | func (x *Port) GetPortNumber() uint32 {
method SetPortNumber (line 310) | func (x *Port) SetPortNumber(v uint32) {
type Port_builder (line 314) | type Port_builder struct
method Build (line 320) | func (b0 Port_builder) Build() *Port {
type Hostname (line 329) | type Hostname struct
method Reset (line 336) | func (x *Hostname) Reset() {
method String (line 343) | func (x *Hostname) String() string {
method ProtoMessage (line 347) | func (*Hostname) ProtoMessage() {}
method ProtoReflect (line 349) | func (x *Hostname) ProtoReflect() protoreflect.Message {
method GetName (line 361) | func (x *Hostname) GetName() string {
method SetName (line 368) | func (x *Hostname) SetName(v string) {
type Hostname_builder (line 372) | type Hostname_builder struct
method Build (line 378) | func (b0 Hostname_builder) Build() *Hostname {
type NetworkEndpoint (line 387) | type NetworkEndpoint struct
method Reset (line 397) | func (x *NetworkEndpoint) Reset() {
method String (line 404) | func (x *NetworkEndpoint) String() string {
method ProtoMessage (line 408) | func (*NetworkEndpoint) ProtoMessage() {}
method ProtoReflect (line 410) | func (x *NetworkEndpoint) ProtoReflect() protoreflect.Message {
method GetType (line 422) | func (x *NetworkEndpoint) GetType() NetworkEndpoint_Type {
method GetIpAddress (line 429) | func (x *NetworkEndpoint) GetIpAddress() *IpAddress {
method GetPort (line 436) | func (x *NetworkEndpoint) GetPort() *Port {
method GetHostname (line 443) | func (x *NetworkEndpoint) GetHostname() *Hostname {
method SetType (line 450) | func (x *NetworkEndpoint) SetType(v NetworkEndpoint_Type) {
method SetIpAddress (line 454) | func (x *NetworkEndpoint) SetIpAddress(v *IpAddress) {
method SetPort (line 458) | func (x *NetworkEndpoint) SetPort(v *Port) {
method SetHostname (line 462) | func (x *NetworkEndpoint) SetHostname(v *Hostname) {
method HasIpAddress (line 466) | func (x *NetworkEndpoint) HasIpAddress() bool {
method HasPort (line 473) | func (x *NetworkEndpoint) HasPort() bool {
method HasHostname (line 480) | func (x *NetworkEndpoint) HasHostname() bool {
method ClearIpAddress (line 487) | func (x *NetworkEndpoint) ClearIpAddress() {
method ClearPort (line 491) | func (x *NetworkEndpoint) ClearPort() {
method ClearHostname (line 495) | func (x *NetworkEndpoint) ClearHostname() {
type NetworkEndpoint_builder (line 499) | type NetworkEndpoint_builder struct
method Build (line 515) | func (b0 NetworkEndpoint_builder) Build() *NetworkEndpoint {
constant file_network_proto_rawDesc (line 528) | file_network_proto_rawDesc = "" +
function init (line 588) | func init() { file_network_proto_init() }
function file_network_proto_init (line 589) | func file_network_proto_init() {
FILE: proto/go/network_service_go_proto/network_service.pb.go
constant _ (line 38) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 40) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type NetworkService (line 44) | type NetworkService struct
method Reset (line 60) | func (x *NetworkService) Reset() {
method String (line 67) | func (x *NetworkService) String() string {
method ProtoMessage (line 71) | func (*NetworkService) ProtoMessage() {}
method ProtoReflect (line 73) | func (x *NetworkService) ProtoReflect() protoreflect.Message {
method GetNetworkEndpoint (line 85) | func (x *NetworkService) GetNetworkEndpoint() *network_go_proto.Networ...
method GetTransportProtocol (line 92) | func (x *NetworkService) GetTransportProtocol() network_go_proto.Trans...
method GetServiceName (line 99) | func (x *NetworkService) GetServiceName() string {
method GetSoftware (line 106) | func (x *NetworkService) GetSoftware() *software_go_proto.Software {
method GetVersionSet (line 113) | func (x *NetworkService) GetVersionSet() *software_go_proto.VersionSet {
method GetBanner (line 120) | func (x *NetworkService) GetBanner() []string {
method GetServiceContext (line 127) | func (x *NetworkService) GetServiceContext() *ServiceContext {
method GetCpes (line 134) | func (x *NetworkService) GetCpes() []string {
method GetSupportedSslVersions (line 141) | func (x *NetworkService) GetSupportedSslVersions() []string {
method GetSupportedHttpMethods (line 148) | func (x *NetworkService) GetSupportedHttpMethods() []string {
method SetNetworkEndpoint (line 155) | func (x *NetworkService) SetNetworkEndpoint(v *network_go_proto.Networ...
method SetTransportProtocol (line 159) | func (x *NetworkService) SetTransportProtocol(v network_go_proto.Trans...
method SetServiceName (line 163) | func (x *NetworkService) SetServiceName(v string) {
method SetSoftware (line 167) | func (x *NetworkService) SetSoftware(v *software_go_proto.Software) {
method SetVersionSet (line 171) | func (x *NetworkService) SetVersionSet(v *software_go_proto.VersionSet) {
method SetBanner (line 175) | func (x *NetworkService) SetBanner(v []string) {
method SetServiceContext (line 179) | func (x *NetworkService) SetServiceContext(v *ServiceContext) {
method SetCpes (line 183) | func (x *NetworkService) SetCpes(v []string) {
method SetSupportedSslVersions (line 187) | func (x *NetworkService) SetSupportedSslVersions(v []string) {
method SetSupportedHttpMethods (line 191) | func (x *NetworkService) SetSupportedHttpMethods(v []string) {
method HasNetworkEndpoint (line 195) | func (x *NetworkService) HasNetworkEndpoint() bool {
method HasSoftware (line 202) | func (x *NetworkService) HasSoftware() bool {
method HasVersionSet (line 209) | func (x *NetworkService) HasVersionSet() bool {
method HasServiceContext (line 216) | func (x *NetworkService) HasServiceContext() bool {
method ClearNetworkEndpoint (line 223) | func (x *NetworkService) ClearNetworkEndpoint() {
method ClearSoftware (line 227) | func (x *NetworkService) ClearSoftware() {
method ClearVersionSet (line 231) | func (x *NetworkService) ClearVersionSet() {
method ClearServiceContext (line 235) | func (x *NetworkService) ClearServiceContext() {
type NetworkService_builder (line 239) | type NetworkService_builder struct
method Build (line 266) | func (b0 NetworkService_builder) Build() *NetworkService {
type ServiceContext (line 284) | type ServiceContext struct
method Reset (line 291) | func (x *ServiceContext) Reset() {
method String (line 298) | func (x *ServiceContext) String() string {
method ProtoMessage (line 302) | func (*ServiceContext) ProtoMessage() {}
method ProtoReflect (line 304) | func (x *ServiceContext) ProtoReflect() protoreflect.Message {
method GetWebServiceContext (line 316) | func (x *ServiceContext) GetWebServiceContext() *WebServiceContext {
method SetWebServiceContext (line 325) | func (x *ServiceContext) SetWebServiceContext(v *WebServiceContext) {
method HasContext (line 333) | func (x *ServiceContext) HasContext() bool {
method HasWebServiceContext (line 340) | func (x *ServiceContext) HasWebServiceContext() bool {
method ClearContext (line 348) | func (x *ServiceContext) ClearContext() {
method ClearWebServiceContext (line 352) | func (x *ServiceContext) ClearWebServiceContext() {
method WhichContext (line 361) | func (x *ServiceContext) WhichContext() case_ServiceContext_Context {
constant ServiceContext_Context_not_set_case (line 358) | ServiceContext_Context_not_set_case case_ServiceContext_Context = 0
constant ServiceContext_WebServiceContext_case (line 359) | ServiceContext_WebServiceContext_case case_ServiceContext_Context = 1
type ServiceContext_builder (line 373) | type ServiceContext_builder struct
metho
Condensed preview — 345 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,872K chars).
[
{
"path": ".dockerignore",
"chars": 203,
"preview": "# Git-related files\n.gitattributes\n.gitignore\n.git/\n\n# IDE files\n.idea/\n.vscode/\n\n# Build cache\n.gradle/\n\n# Documentatio"
},
{
"path": ".gitattributes",
"chars": 154,
"preview": "#\n# https://help.github.com/articles/dealing-with-line-endings/\n#\n# These are explicitly windows files and should use cr"
},
{
"path": ".github/workflows/core-build.yml",
"chars": 587,
"preview": "name: core-build\n\non:\n pull_request:\n workflow_dispatch:\n\nenv:\n REGISTRY: ghcr.io\n IMAGE_NAME: google/tsunami-scanne"
},
{
"path": ".github/workflows/core-push.yml",
"chars": 1360,
"preview": "name: core-push\n\non:\n push:\n branches:\n - master\n workflow_dispatch:\n\nenv:\n REGISTRY: ghcr.io\n IMAGE_NAME: g"
},
{
"path": ".github/workflows/devel-push.yml",
"chars": 1364,
"preview": "name: devel-push\n\non:\n schedule:\n - cron: \"0 */4 * * *\"\n workflow_dispatch:\n\nenv:\n REGISTRY: ghcr.io\n IMAGE_NAME:"
},
{
"path": ".github/workflows/full-push.yml",
"chars": 1361,
"preview": "name: full-push\n\non:\n schedule:\n - cron: \"0 */4 * * *\"\n workflow_dispatch:\n\nenv:\n REGISTRY: ghcr.io\n IMAGE_NAME: "
},
{
"path": ".gitignore",
"chars": 216,
"preview": "# Gradle\nbuild\ngradle.properties\n.gradle\nlocal.properties\nout\n\n# IntelliJ IDEA\n.idea\n*.iml\n*.ipr\n*.iws\nclasses\n\n# Eclips"
},
{
"path": "LICENSE",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 1597,
"preview": "# Tsunami\n\n\n\nTsun"
},
{
"path": "build.gradle",
"chars": 2441,
"preview": "// Current gradle version 6.5.\n\nplugins {\n id 'net.ltgt.errorprone' apply false version \"4.2.0\"\n id \"com.gradleup."
},
{
"path": "common/README.md",
"chars": 132,
"preview": "# Tsunami Common Libraries\n\n## Overview\n\nThis module provides a set of common libraries and utilities for Tsunami\nSecuri"
},
{
"path": "common/build.gradle",
"chars": 1656,
"preview": "description = 'Tsunami: Common'\n\ndependencies {\n implementation project(':tsunami-proto')\n\n implementation \"com.be"
},
{
"path": "common/src/main/java/com/google/tsunami/common/ErrorCode.java",
"chars": 800,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/TsunamiException.java",
"chars": 1798,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/cli/CliOption.java",
"chars": 1243,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/cli/CliOptionsModule.java",
"chars": 3535,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/command/CommandExecutionThreadPool.java",
"chars": 916,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/command/CommandExecutor.java",
"chars": 5892,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/command/CommandExecutorFactory.java",
"chars": 1563,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/command/CommandExecutorModule.java",
"chars": 1251,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/concurrent/BaseThreadPoolModule.java",
"chars": 10197,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/concurrent/ScheduledThreadPoolModule.java",
"chars": 3539,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/concurrent/ThreadPoolModule.java",
"chars": 5822,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/config/ConfigException.java",
"chars": 1042,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/config/ConfigLoader.java",
"chars": 920,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/config/ConfigModule.java",
"chars": 2909,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/config/TsunamiConfig.java",
"chars": 5294,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/config/YamlConfigLoader.java",
"chars": 2011,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/config/annotations/ConfigProperties.java",
"chars": 2062,
"preview": "/*\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/data/NetworkEndpointUtils.java",
"chars": 11140,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/data/NetworkServiceUtils.java",
"chars": 8520,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/io/archiving/Archiver.java",
"chars": 1948,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/io/archiving/GoogleCloudStorageArchiver.java",
"chars": 4545,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/io/archiving/GoogleCloudStorageArchiverModule.java",
"chars": 1005,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/io/archiving/RawFileArchiver.java",
"chars": 1642,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeArchiver.java",
"chars": 3565,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeGoogleCloudStorageArchivers.java",
"chars": 3372,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeGoogleCloudStorageArchiversModule.java",
"chars": 1383,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeRawFileArchiver.java",
"chars": 1452,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/io/archiving/testing/FakeRawFileArchiverModule.java",
"chars": 1589,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/FuzzingUtils.java",
"chars": 7670,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/UrlUtils.java",
"chars": 4715,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/db/ConnectionProvider.java",
"chars": 1084,
"preview": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/db/ConnectionProviderInterface.java",
"chars": 908,
"preview": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/HttpClient.java",
"chars": 4153,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/HttpClientCliOptions.java",
"chars": 3126,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/HttpClientConfigProperties.java",
"chars": 1886,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/HttpClientModule.java",
"chars": 14343,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/HttpHeaders.java",
"chars": 6038,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/HttpMethod.java",
"chars": 978,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/HttpRequest.java",
"chars": 6213,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/HttpResponse.java",
"chars": 3475,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/HttpStatus.java",
"chars": 5352,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/OkHttpHttpClient.java",
"chars": 15039,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/javanet/ConnectionFactory.java",
"chars": 1189,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/http/javanet/DefaultConnectionFactory.java",
"chars": 2383,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/socket/DefaultTsunamiSocketFactory.java",
"chars": 9949,
"preview": "/*\n * Copyright 2026 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/socket/TsunamiSocketFactory.java",
"chars": 10049,
"preview": "/*\n * Copyright 2026 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/socket/TsunamiSocketFactoryCliOptions.java",
"chars": 3491,
"preview": "/*\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/socket/TsunamiSocketFactoryConfigProperties.java",
"chars": 3148,
"preview": "/*\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/net/socket/TsunamiSocketFactoryModule.java",
"chars": 6931,
"preview": "/*\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/reflection/ClassGraphModule.java",
"chars": 1194,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/reflection/RuntimeClassGraphScanResult.java",
"chars": 1178,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/server/CompactRunRequestHelper.java",
"chars": 2824,
"preview": "/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/server/LanguageServerCommand.java",
"chars": 1952,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/time/SystemUtcClockModule.java",
"chars": 958,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/time/UtcClock.java",
"chars": 895,
"preview": "/*\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/time/testing/FakeUtcClock.java",
"chars": 3173,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/time/testing/FakeUtcClockModule.java",
"chars": 1394,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/version/ComparisonUtility.java",
"chars": 1979,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/version/KnownQualifier.java",
"chars": 1958,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/version/Segment.java",
"chars": 4057,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/version/Token.java",
"chars": 3546,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/version/Version.java",
"chars": 6109,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/version/VersionRange.java",
"chars": 5855,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/main/java/com/google/tsunami/common/version/VersionSet.java",
"chars": 2869,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/cli/CliOptionsModuleTest.java",
"chars": 5406,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/command/CommandExecutorFactoryTest.java",
"chars": 1448,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/command/CommandExecutorTest.java",
"chars": 3538,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/concurrent/BaseThreadPoolModuleTest.java",
"chars": 3741,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/concurrent/ScheduledThreadPoolModuleTest.java",
"chars": 2638,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/concurrent/ThreadPoolModuleTest.java",
"chars": 4053,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/config/ConfigModuleTest.java",
"chars": 4706,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/config/TsunamiConfigTest.java",
"chars": 6524,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/config/YamlConfigLoaderTest.java",
"chars": 1913,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/data/NetworkEndpointUtilsTest.java",
"chars": 16765,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/data/NetworkServiceUtilsTest.java",
"chars": 14383,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/io/archiving/ArchiverTestUtils.java",
"chars": 1225,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/io/archiving/GoogleCloudStorageArchiverTest.java",
"chars": 7047,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/io/archiving/RawFileArchiverTest.java",
"chars": 2907,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/net/FuzzingUtilsTest.java",
"chars": 6403,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/net/UrlUtilsTest.java",
"chars": 6141,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/net/http/HttpClientModuleTest.java",
"chars": 10014,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/net/http/HttpHeadersTest.java",
"chars": 7429,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/net/http/HttpRequestTest.java",
"chars": 2580,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/net/http/HttpResponseTest.java",
"chars": 4832,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/net/http/OkHttpHttpClientTest.java",
"chars": 33769,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/net/socket/DefaultTsunamiSocketFactoryTest.java",
"chars": 10291,
"preview": "/*\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/net/socket/TsunamiSocketFactoryCliOptionsTest.java",
"chars": 3265,
"preview": "/*\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/net/socket/TsunamiSocketFactoryModuleTest.java",
"chars": 6352,
"preview": "/*\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/server/CompactRunRequestHelperTest.java",
"chars": 4492,
"preview": "/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/time/SystemUtcClockModuleTest.java",
"chars": 1428,
"preview": "/*\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/time/testing/FakeUtcClockModuleTest.java",
"chars": 1965,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/time/testing/FakeUtcClockTest.java",
"chars": 1944,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/version/ComparisonUtilityTest.java",
"chars": 4207,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/version/EqualsTestCase.java",
"chars": 972,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/version/KnownQualifierTest.java",
"chars": 2957,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/version/LessThanTestCase.java",
"chars": 984,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/version/SegmentTest.java",
"chars": 5861,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/version/TokenTest.java",
"chars": 5163,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/version/VersionRangeTest.java",
"chars": 5242,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/version/VersionSetTest.java",
"chars": 2183,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/java/com/google/tsunami/common/version/VersionTest.java",
"chars": 12861,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "common/src/test/resources/com/google/tsunami/common/net/http/testdata/README.md",
"chars": 530,
"preview": "# HTTP Lib Testdata\n\n## tsunami_test_server.p12\n\nThis is a PKCS12 self-signed server key/cert file. This file was genera"
},
{
"path": "core.Dockerfile",
"chars": 1600,
"preview": "# Stage 1: Build phase\n\nFROM ghcr.io/google/tsunami-scanner-devel:latest AS build\n\n## build the core engine\nWORKDIR /usr"
},
{
"path": "devel.Dockerfile",
"chars": 1485,
"preview": "FROM ubuntu:latest\n\nRUN apt-get update \\\n && apt-get install -y --no-install-recommends git openjdk-21-jdk ca-certificat"
},
{
"path": "docs/_config.yml",
"chars": 200,
"preview": "remote_theme: pages-themes/cayman@v0.2.0\nurl: https://google.github.io\nbaseurl: /tsunami-security-scanner\npaginate: 5\npa"
},
{
"path": "docs/_data/nav.yml",
"chars": 114,
"preview": "- title: \"What's new\"\n path: /\n\n- title: \"All articles\"\n path: /blog/\n\n- title: \"Documentation\"\n path: /howto/\n"
},
{
"path": "docs/_includes/nav.html",
"chars": 456,
"preview": "{% for nav in site.data.nav %}\n {% if nav.subcategories != null %}\n {% for subcategory in nav.subcategories %}\n "
},
{
"path": "docs/_layouts/default.html",
"chars": 2013,
"preview": "<!DOCTYPE html>\n<html lang=\"{{ site.lang | default: \"en-US\" }}\">\n <head>\n <meta charset=\"UTF-8\">\n\n{% seo %}\n <lin"
},
{
"path": "docs/_layouts/home.html",
"chars": 45,
"preview": "---\nlayout: none\n---\n\n{{ site.posts.first }}\n"
},
{
"path": "docs/_layouts/post.html",
"chars": 187,
"preview": "---\nlayout: default\n---\n<h3>\n Posted on {{ page.date | date_to_long_string: \"ordinal\" }} by\n {% for author in page.au"
},
{
"path": "docs/_posts/2024-03-19-tsunami-network-scanner-ai-security.md",
"chars": 2851,
"preview": "---\nauthors:\n- name: Annie Mao\nexcerpt: 'Interested in creating an AI-related plugin for the Tsunami network scanner and"
},
{
"path": "docs/_posts/2025-06-18-changes-to-tsunami.md",
"chars": 4941,
"preview": "---\nauthors:\n\n- name: Pierre Precourt\nexcerpt: ‘Templated plugins are now the default for writing plugins and making the"
},
{
"path": "docs/_posts/2025-10-16-october-update-tsunami-prp.md",
"chars": 4494,
"preview": "# October update - Tsunami reward program\n\n## Improving the PRP situation\n\nSince our\n[last update in June](https://googl"
},
{
"path": "docs/about/index.md",
"chars": 2124,
"preview": "# About Tsunami\n\n## <a name=\"why_tsunami\"></a>Why Tsunami?\n\nWhen security vulnerabilities or misconfigurations are activ"
},
{
"path": "docs/assets/css/style.scss",
"chars": 192,
"preview": "---\n---\n\n@import '{{ site.theme }}';\n\n.pagination {\n text-align: center;\n background-color: #eee;\n border-radius: 0.3"
},
{
"path": "docs/blog/index.html",
"chars": 719,
"preview": "---\ntitle: Posts\nlayout: default\n---\n\n{% for post in paginator.posts %}\n <h1><a href=\"{{ post.url | relative_url }}\">{{"
},
{
"path": "docs/contribute/code-of-conduct.md",
"chars": 3175,
"preview": "# Google Open Source Community Guidelines\n\nAt Google, we recognize and celebrate the creativity and collaboration of ope"
},
{
"path": "docs/contribute/contributing.md",
"chars": 1097,
"preview": "# How to Contribute\n\nWe'd love to accept your patches and contributions to this project. There are\njust a few small guid"
},
{
"path": "docs/contribute/index.md",
"chars": 109,
"preview": "# Contributing to Tsunami\n\n{% include_relative contributing.md %}\n\n{% include_relative code-of-conduct.md %}\n"
},
{
"path": "docs/howto/common-patterns.md",
"chars": 9409,
"preview": "# Common detector patterns\n\n### Running only for a specific service\n\n*Use case: I want my detector to only run for web a"
},
{
"path": "docs/howto/howto.md",
"chars": 8290,
"preview": "# Build and run Tsunami\n\n## Tsunami docker's environment\n\nWe provide a set of Docker images to help you build and use Ts"
},
{
"path": "docs/howto/index.md",
"chars": 1045,
"preview": "# Tsunami documentation\n\nWelcome to the Tsunami community, we are thrilled that you want to contribute.\nThis page contai"
},
{
"path": "docs/howto/new-detector/new-detector-java.md",
"chars": 7870,
"preview": "# Writing a Tsunami detector (Java)\n\nNOTE: We now expect you to write plugins using the templated format first. Only\nres"
},
{
"path": "docs/howto/new-detector/templated/00-getting-started.md",
"chars": 1344,
"preview": "\n# Getting started with templated plugins\n\nIn this documentation, you will learn how to write a plugin for Tsunami in th"
},
{
"path": "docs/howto/new-detector/templated/01-introduction.md",
"chars": 3298,
"preview": "\n# Introduction\n\n## What is a templated plugin?\n\nIn the past, if you wanted to write a Tsunami detector, you would need "
},
{
"path": "docs/howto/new-detector/templated/02-bootstrapping.md",
"chars": 4641,
"preview": "\n# Bootstrapping the plugin\n\n*This section assumes that you already know how to\n[build and run Tsunami](https://google.g"
},
{
"path": "docs/howto/new-detector/templated/03-first-actions.md",
"chars": 3095,
"preview": "\n# Writing the first actions\n\nEach action is defined by a name and a subtype. A subtype defines what the\naction is able "
},
{
"path": "docs/howto/new-detector/templated/04-workflows.md",
"chars": 1494,
"preview": "\n# Assembling the workflow\n\nA workflow is simply a list of the actions to be executed, in order:\n\n```proto\nworkflows: {\n"
},
{
"path": "docs/howto/new-detector/templated/05-variables.md",
"chars": 3964,
"preview": "\n# Using variables\n\nIn our action, we have hardcoded our payload, which is not super convenient and\nreadable:\n\n```proto\n"
},
{
"path": "docs/howto/new-detector/templated/06-callback-server.md",
"chars": 3085,
"preview": "\n# Using the callback server\n\nIf you wrote plugins for Tsunami before, you know about the callback server. If\nyou have n"
},
{
"path": "docs/howto/new-detector/templated/07-cleanup-actions.md",
"chars": 1737,
"preview": "\n# Cleanup actions\n\nIn our example, none of the defined actions will modify the target. But what if\nwe had some actions "
},
{
"path": "docs/howto/new-detector/templated/08-writing-unit-tests.md",
"chars": 4049,
"preview": "\n# Writing unit tests\n\nFor every workflow, we expect to see associated unit tests for each of your\ncontributions. If uni"
},
{
"path": "docs/howto/new-detector/templated/appendix-naming-actions.md",
"chars": 197,
"preview": "# Convention: How to name actions\n\nActions must be named using the `[a-zA-Z0-9_]` character set. For example\n`this_is_my"
},
{
"path": "docs/howto/new-detector/templated/appendix-naming-plugin.md",
"chars": 921,
"preview": "# Convention: How to name a plugin\n\nThe plugin name and filename should be identical as it makes for easier\ndiscoverabil"
},
{
"path": "docs/howto/new-detector/templated/appendix-naming-tests.md",
"chars": 212,
"preview": "# How to name unit tests\n\nUse `condition_outcome` as the naming schema for your tests. That explicitly\nmeans that you sh"
},
{
"path": "docs/howto/new-detector/templated/appendix-using-linter.md",
"chars": 763,
"preview": "\n# Using the linter\n\nFor all plugins written using our configuration format, we expect the plugins to\nbe linted.\n\nThe li"
},
{
"path": "docs/howto/new-detector/templated/glossary-predefined-variables.md",
"chars": 1986,
"preview": "# Predefined variables\n\nTsunami will provide a predefined set of variable to the environment that you\ncan make use of in"
},
{
"path": "docs/howto/new-detector/templated/glossary-tests-magic-uri.md",
"chars": 327,
"preview": "## Magic tests URIs\n\nThe following URIs are considered \"magic\" in tests when using the mock HTTP\nserver:\n\n- `TSUNAMI_MAG"
},
{
"path": "docs/howto/orchestration.md",
"chars": 4616,
"preview": "# Tsunami Scan Orchestration\n\n## Overview\n\nTsunami follows a hardcoded 2-step process when scanning a publicly\nexposed n"
},
{
"path": "docs/index.md",
"chars": 0,
"preview": ""
},
{
"path": "full.Dockerfile",
"chars": 2802,
"preview": "# Core engine\nFROM ghcr.io/google/tsunami-scanner-core:latest AS core\n\n# Callback server\nFROM ghcr.io/google/tsunami-sec"
},
{
"path": "go.mod",
"chars": 61,
"preview": "module github.com/google/tsunami-security-scanner\n\ngo 1.22.0\n"
},
{
"path": "main/README.md",
"chars": 108,
"preview": "# Tsunami Main\n\n## Overview\n\nThis module provides the entry point for starting up Tsunami Security Scanner.\n"
},
{
"path": "main/build.gradle",
"chars": 1925,
"preview": "plugins {\n id 'application'\n id 'com.gradleup.shadow' version \"8.3.6\"\n}\n\ndescription = 'Tsunami: main'\n\ndependenci"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/LanguageServerOptions.java",
"chars": 6178,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/ScanResultsArchiver.java",
"chars": 4771,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/ScanResultsArchiverModule.java",
"chars": 828,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/TsunamiCli.java",
"chars": 14101,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/option/MainCliOptions.java",
"chars": 3591,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/option/OutputDataFormat.java",
"chars": 1334,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/option/validator/IpV4Validator.java",
"chars": 999,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/option/validator/IpV6Validator.java",
"chars": 999,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/option/validator/IpValidator.java",
"chars": 1492,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/server/RemoteServerLoader.java",
"chars": 3577,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/main/java/com/google/tsunami/main/cli/server/RemoteServerLoaderModule.java",
"chars": 1297,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/test/java/com/google/tsunami/main/cli/LanguageServerOptionsTest.java",
"chars": 3573,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/test/java/com/google/tsunami/main/cli/ScanResultsArchiverTest.java",
"chars": 7876,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/test/java/com/google/tsunami/main/cli/TsunamiCliTest.java",
"chars": 15891,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/test/java/com/google/tsunami/main/cli/option/MainCliOptionsTest.java",
"chars": 1700,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/test/java/com/google/tsunami/main/cli/option/OutputDataFormatTest.java",
"chars": 1542,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/test/java/com/google/tsunami/main/cli/option/validator/IpV4ValidatorTest.java",
"chars": 1325,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/test/java/com/google/tsunami/main/cli/option/validator/IpV6ValidatorTest.java",
"chars": 1581,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/test/java/com/google/tsunami/main/cli/option/validator/IpValidatorTest.java",
"chars": 2021,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "main/src/test/java/com/google/tsunami/main/cli/server/RemoteServerLoaderTest.java",
"chars": 2603,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/README.md",
"chars": 128,
"preview": "# Tsunami Plugin Module\n\n## Overview\n\nThis module provides plugin development and management APIs for Tsunami\nSecurity S"
},
{
"path": "plugin/build.gradle",
"chars": 2018,
"preview": "\ndescription = 'Tsunami: Plugin'\n\ndef tcsRepoBranch = System.getenv(\"GITBRANCH_TSUNAMI_TCS\") ?: \"stable\"\n\ndependencies {"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/LanguageServerException.java",
"chars": 1081,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginBootstrapModule.java",
"chars": 3185,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginDefinition.java",
"chars": 5393,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginExecutionException.java",
"chars": 1091,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginExecutionModule.java",
"chars": 1239,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginExecutionResult.java",
"chars": 2156,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginExecutionThreadPool.java",
"chars": 907,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginExecutor.java",
"chars": 2223,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginExecutorImpl.java",
"chars": 4494,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginExecutorModule.java",
"chars": 896,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginLoadingModule.java",
"chars": 5026,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginManager.java",
"chars": 16816,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginManagerCliOptions.java",
"chars": 1855,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginServiceClient.java",
"chars": 3715,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PluginType.java",
"chars": 1131,
"preview": "/*\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/PortScanner.java",
"chars": 1369,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/RemoteVulnDetector.java",
"chars": 1528,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/RemoteVulnDetectorImpl.java",
"chars": 7119,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/RemoteVulnDetectorLoadingModule.java",
"chars": 5775,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/ServiceFingerprinter.java",
"chars": 1830,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/TcsClient.java",
"chars": 5909,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "plugin/src/main/java/com/google/tsunami/plugin/TcsClientCliOptions.java",
"chars": 1430,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
}
]
// ... and 145 more files (download for full content)
About this extraction
This page contains the full source code of the google/tsunami-security-scanner GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 345 files (1.7 MB), approximately 477.8k tokens, and a symbol index with 3673 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.