/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2015 The ZAP Development Team
*
* 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 org.zaproxy.zap;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.parosproxy.paros.CommandLine;
import org.parosproxy.paros.control.Control;
import org.zaproxy.zap.control.AddOn;
import org.zaproxy.zap.control.AddOnLoader;
import org.zaproxy.zap.control.AddOnRunIssuesUtils;
import org.zaproxy.zap.control.ExtensionFactory;
import org.zaproxy.zap.model.SessionUtils;
/**
* A {@code ZapBootstrap} with common functionalities for headless modes (command line and daemon).
*
* @since 2.4.2
*/
abstract class HeadlessBootstrap extends ZapBootstrap {
public HeadlessBootstrap(CommandLine args) {
super(args);
// XXX Do not force headless to allow to run JxBrowser in daemon mode,
// at least until it can be run without a window/dialogue.
// System.setProperty("java.awt.headless", "true");
}
/**
* Initialises the {@code Control} singleton without view and proxy.
*
* @return the initialised {@code Control} singleton.
* @see Control#initSingletonWithoutViewAndProxy(org.zaproxy.zap.control.ControlOverrides)
*/
protected Control initControl() {
Control.initSingletonWithoutViewAndProxy(getControlOverrides());
return Control.getSingleton();
}
/**
* Gets the logger of the class. Used to log errors/warnings that occur during bootstrap.
*
* @return the logger of the class, must not be {@code null}.
*/
protected abstract Logger getLogger();
/**
* Handles command line session related arguments, synchronously.
*
* @param control the {@code Control} singleton
* @return {@code true} if the arguments were handled successfully, {@code false} otherwise.
*/
protected boolean handleCmdLineSessionArgsSynchronously(Control control) {
if (getArgs().isEnabled(CommandLine.SESSION) && getArgs().isEnabled(CommandLine.NEW_SESSION)) {
System.err.println(
"Error: Invalid command line options: option '" + CommandLine.SESSION + "' not allowed with option '"
+ CommandLine.NEW_SESSION + "'");
return false;
}
if (getArgs().isEnabled(CommandLine.SESSION)) {
Path sessionPath = SessionUtils.getSessionPath(getArgs().getArgument(CommandLine.SESSION));
String absolutePath = sessionPath.toAbsolutePath().toString();
try {
control.runCommandLineOpenSession(absolutePath);
} catch (Exception e) {
getLogger().error(e.getMessage(), e);
System.err.println("Failed to open session: " + absolutePath);
e.printStackTrace(System.err);
return false;
}
} else if (getArgs().isEnabled(CommandLine.NEW_SESSION)) {
Path sessionPath = SessionUtils.getSessionPath(getArgs().getArgument(CommandLine.NEW_SESSION));
String absolutePath = sessionPath.toAbsolutePath().toString();
if (Files.exists(sessionPath)) {
System.err.println("Failed to create a new session, file already exists: " + absolutePath);
return false;
}
try {
control.runCommandLineNewSession(absolutePath);
} catch (Exception e) {
getLogger().error(e.getMessage(), e);
System.err.println("Failed to create a new session: " + absolutePath);
e.printStackTrace(System.err);
return false;
}
}
return true;
}
/**
* Warns, through logging, about add-ons and extensions that are no longer runnable because of changes in its dependencies.
*/
protected void warnAddOnsAndExtensionsNoLongerRunnable() {
final AddOnLoader addOnLoader = ExtensionFactory.getAddOnLoader();
List<String> idsAddOnsNoLongerRunning = addOnLoader.getIdsAddOnsWithRunningIssuesSinceLastRun();
if (idsAddOnsNoLongerRunning.isEmpty()) {
return;
}
List<AddOn> addOnsNoLongerRunning = new ArrayList<>(idsAddOnsNoLongerRunning.size());
for (String id : idsAddOnsNoLongerRunning) {
addOnsNoLongerRunning.add(addOnLoader.getAddOnCollection().getAddOn(id));
}
for (AddOn addOn : addOnsNoLongerRunning) {
AddOn.AddOnRunRequirements requirements = addOn
.calculateRunRequirements(addOnLoader.getAddOnCollection().getAddOns());
List<String> issues = AddOnRunIssuesUtils.getRunningIssues(requirements);
if (issues.isEmpty()) {
issues = AddOnRunIssuesUtils.getExtensionsRunningIssues(requirements);
}
getLogger().warn(
"Add-on \"" + addOn.getId()
+ "\" or its extensions will no longer be run until its requirements are restored: " + issues);
}
}
}