<commit_before>/*
* Zed Attack Proxy (ZAP) and its related class files.
 * 
 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
 * 
 * Copyright 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.extension.ascan;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.parosproxy.paros.Constant;
import org.zaproxy.zap.utils.ZapXmlConfiguration;

public class PolicyManager {
	
	public static final String POLICY_EXTENSION = ".policy";
	
	private static final String DEFAULT_POLICY_NAME = Constant.messages.getString("ascan.policymgr.default.name");
    public static final String ILLEGAL_POLICY_NAME_CHRS = "/`?*\\<>|\":\t\n\r";

	private List<String> allPolicyNames = null;
	private ExtensionActiveScan extension;

    private static final Logger logger = Logger.getLogger(PolicyManager.class);

    public PolicyManager(ExtensionActiveScan extension) {
    	this.extension = extension;
    }
    
    public void init() {
    	// Force load
    	getAllPolicyNames();
    }
    
	public synchronized List<String> getAllPolicyNames() {
		if (allPolicyNames == null) {
			allPolicyNames = new ArrayList<String>();
			String[] files = Constant.getPoliciesDir().list();
			if (files != null) {
				for (String file : files) {
					if (file.endsWith(POLICY_EXTENSION)) {
						logger.debug("Found policy file " + file);
						allPolicyNames.add(file.substring(0, file.lastIndexOf(POLICY_EXTENSION)));
					}
				}
			}
			if (allPolicyNames.size() == 0) {
				// No policies :( Create a default one
				ScanPolicy defaultPolicy = new ScanPolicy();
				defaultPolicy.setName(DEFAULT_POLICY_NAME);
				// Load from the 'old' configs
				defaultPolicy.getPluginFactory().loadAllPlugin(extension.getScannerParam().getConfig());
				try {
					// Note this will add the name to allPolicyNames
					this.savePolicy(defaultPolicy);
				} catch (ConfigurationException e) {
					logger.debug("Failed to create default scan policy in " + Constant.getPoliciesDir().getAbsolutePath(), e);
				}
			}
			
			Collections.sort(allPolicyNames);
		}
		return allPolicyNames;
	}

	public void savePolicy (ScanPolicy policy) throws ConfigurationException {
		this.savePolicy(policy, null);
	}

	public void savePolicy (ScanPolicy policy, String previousName) throws ConfigurationException {
		logger.debug("Save policy " + policy.getName());

		File file = new File(Constant.getPoliciesDir(), policy.getName() + POLICY_EXTENSION);

		ZapXmlConfiguration conf = new ZapXmlConfiguration();
    	conf.setProperty("policy", policy.getName());
        conf.setProperty("scanner.level", policy.getDefaultThreshold().name());
        conf.setProperty("scanner.strength", policy.getDefaultStrength().name());

		policy.getPluginFactory().saveTo(conf);

    	conf.save(file);
    	
    	if (previousName != null && previousName.length() > 0) {
    		allPolicyNames.remove(previousName);
    	}
    	if (!allPolicyNames.contains(policy.getName())) {
    		allPolicyNames.add(policy.getName());
    		Collections.sort(allPolicyNames);
    	}
	}
	
	/**
	 * Tells whether or not a scan policy with the given {@code name} exists.
	 *
	 * @param name the name of the scan policy
	 * @return {@code true} if the scan policy exists, {@code false} otherwise
	 * @since 2.4.3
	 */
	public static boolean policyExists(String name) {
		return (new File(Constant.getPoliciesDir(), name + POLICY_EXTENSION)).exists();
		
	}

	public ScanPolicy getPolicy (String name) throws ConfigurationException {
		return this.loadPolicy(new File(Constant.getPoliciesDir(), name + POLICY_EXTENSION));
	}

	public ScanPolicy loadPolicy (String name) throws ConfigurationException {
		return this.loadPolicy(new File(Constant.getPoliciesDir(), name + POLICY_EXTENSION));
	}
	
	private ScanPolicy loadPolicy (File file) throws ConfigurationException {
		ScanPolicy policy = new ScanPolicy(new ZapXmlConfiguration(file));
		if (! file.getName().equals(policy.getName() + POLICY_EXTENSION)) {
			// The file name takes precedence in case theres another policy with the same name
			policy.setName(file.getName().substring(0, file.getName().indexOf(POLICY_EXTENSION)));
		}
		
		return policy;
	}
	
	public void importPolicy (File file) throws ConfigurationException, IOException {
		logger.debug("Import policy from " + file.getAbsolutePath());
		ScanPolicy policy = new ScanPolicy(new ZapXmlConfiguration(file));
    	String baseName = file.getName();
    	if (baseName.endsWith(POLICY_EXTENSION)) {
    		// Stip off the extension for the 'friendly name' and if we need to prevent overwriting an existing one
    		baseName = baseName.substring(0, baseName.indexOf(POLICY_EXTENSION));
    	}<commit_msg>Use file name case when loading policies from file<commit_after>/*
* Zed Attack Proxy (ZAP) and its related class files.
 * 
 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
 * 
 * Copyright 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.extension.ascan;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.parosproxy.paros.Constant;
import org.zaproxy.zap.utils.ZapXmlConfiguration;

public class PolicyManager {
	
	public static final String POLICY_EXTENSION = ".policy";
	
	private static final String DEFAULT_POLICY_NAME = Constant.messages.getString("ascan.policymgr.default.name");
    public static final String ILLEGAL_POLICY_NAME_CHRS = "/`?*\\<>|\":\t\n\r";

	private List<String> allPolicyNames = null;
	private ExtensionActiveScan extension;

    private static final Logger logger = Logger.getLogger(PolicyManager.class);

    public PolicyManager(ExtensionActiveScan extension) {
    	this.extension = extension;
    }
    
    public void init() {
    	// Force load
    	getAllPolicyNames();
    }
    
	public synchronized List<String> getAllPolicyNames() {
		if (allPolicyNames == null) {
			allPolicyNames = new ArrayList<String>();
			String[] files = Constant.getPoliciesDir().list();
			if (files != null) {
				for (String file : files) {
					if (file.endsWith(POLICY_EXTENSION)) {
						logger.debug("Found policy file " + file);
						allPolicyNames.add(file.substring(0, file.lastIndexOf(POLICY_EXTENSION)));
					}
				}
			}
			if (allPolicyNames.size() == 0) {
				// No policies :( Create a default one
				ScanPolicy defaultPolicy = new ScanPolicy();
				defaultPolicy.setName(DEFAULT_POLICY_NAME);
				// Load from the 'old' configs
				defaultPolicy.getPluginFactory().loadAllPlugin(extension.getScannerParam().getConfig());
				try {
					// Note this will add the name to allPolicyNames
					this.savePolicy(defaultPolicy);
				} catch (ConfigurationException e) {
					logger.debug("Failed to create default scan policy in " + Constant.getPoliciesDir().getAbsolutePath(), e);
				}
			}
			
			Collections.sort(allPolicyNames);
		}
		return allPolicyNames;
	}

	public void savePolicy (ScanPolicy policy) throws ConfigurationException {
		this.savePolicy(policy, null);
	}

	public void savePolicy (ScanPolicy policy, String previousName) throws ConfigurationException {
		logger.debug("Save policy " + policy.getName());

		File file = new File(Constant.getPoliciesDir(), policy.getName() + POLICY_EXTENSION);

		ZapXmlConfiguration conf = new ZapXmlConfiguration();
    	conf.setProperty("policy", policy.getName());
        conf.setProperty("scanner.level", policy.getDefaultThreshold().name());
        conf.setProperty("scanner.strength", policy.getDefaultStrength().name());

		policy.getPluginFactory().saveTo(conf);

    	conf.save(file);
    	
    	if (previousName != null && previousName.length() > 0) {
    		allPolicyNames.remove(previousName);
    	}
    	if (!allPolicyNames.contains(policy.getName())) {
    		allPolicyNames.add(policy.getName());
    		Collections.sort(allPolicyNames);
    	}
	}
	
	/**
	 * Tells whether or not a scan policy with the given {@code name} exists.
	 *
	 * @param name the name of the scan policy
	 * @return {@code true} if the scan policy exists, {@code false} otherwise
	 * @since 2.4.3
	 */
	public static boolean policyExists(String name) {
		return (new File(Constant.getPoliciesDir(), name + POLICY_EXTENSION)).exists();
		
	}

	public ScanPolicy getPolicy (String name) throws ConfigurationException {
		return this.loadPolicy(new File(Constant.getPoliciesDir(), name + POLICY_EXTENSION));
	}

	public ScanPolicy loadPolicy (String name) throws ConfigurationException {
		return this.loadPolicy(new File(Constant.getPoliciesDir(), name + POLICY_EXTENSION));
	}
	
	private ScanPolicy loadPolicy (File file) throws ConfigurationException {
		File policyFile;
		try {
			// Obtain the name of the file in correct case, for DEFAULT_POLICY_NAME it might not be exactly the same if the file
			// system is case insensitive, thus not matching with the name read directly from the file system (method
			// getAllPolicyNames()).
			policyFile = file.toPath().toRealPath().toFile();
		} catch (IOException e) {
			throw new ConfigurationException("Failed to obtain the real path of the policy file:", e);
		}
		ScanPolicy policy = new ScanPolicy(new ZapXmlConfiguration(policyFile));
		if (! policyFile.getName().equals(policy.getName() + POLICY_EXTENSION)) {
			// The file name takes precedence in case theres another policy with the same name
			policy.setName(policyFile.getName().substring(0, policyFile.getName().indexOf(POLICY_EXTENSION)));
		}
		
		return policy;
	}
	
	public void importPolicy (File file) throws ConfigurationException, IOException {
		logger.debug("Import policy from " + file.getAbsolutePath());
		ScanPolicy policy = new ScanPolicy(new ZapXmlConfiguration(file));
    	String baseName = file.getName();
    	if (baseName.endsWith(POLICY_EXTENSION)) {
    		// Stip off the extension for the 'friendly name' and if we need to prevent overwriting an existing one
    		baseName = baseName.substring(0, baseName.indexOf(POLICY_EXTENSION));
    	}
{'fraction_non_alphanumeric': 0.10496653751320888, 'fraction_numerical': 0.0022895385699189855, 'mean_word_length': 4.052046263345196, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4149569', 'n_tokens_mistral': 3531, 'n_tokens_neox': 3199, 'n_words': 936}