/** * ESUP-Portail Helpdesk - Copyright (c) 2004-2009 ESUP-Portail consortium. */ package org.esupportail.helpdesk.domain.departmentSelection.conditions; import java.net.InetAddress; import org.esupportail.helpdesk.domain.DomainService; import org.esupportail.helpdesk.domain.departmentSelection.DepartmentSelectionCompileError; /** * A condition that is matched when the client's IP address matches a given pattern. */ public class ClientIpCondition extends AbstractClientCondition { /** * The serialization id. */ private static final long serialVersionUID = -3636436056399797050L; /** Magic number. */ private static final int CONST_32 = 32; /** Magic number. */ private static final int CONST_8 = 8; /** * The pattern the client should match. */ private String pattern; /** * Empty constructor (for Digester). */ public ClientIpCondition() { super(); } /** * Set the pattern. * @param pattern a pattern, such as: * - 148.60. * - 148.60.0.0/255.255.0.0 * - 148.60.0.0/16 */ public void setPattern(final String pattern) { this.pattern = pattern; } /** * @see org.esupportail.helpdesk.domain.departmentSelection.conditions.AbstractClientCondition * #isMatchedInternal( * org.esupportail.helpdesk.domain.DomainService, java.net.InetAddress) */ @Override protected boolean isMatchedInternal( @SuppressWarnings("unused") final DomainService domainService, final InetAddress client) { boolean result = false; String maskConfig = null; String ipClient = null; String ip = null; String mask = null; if (this.pattern.endsWith(".")) { if (client.getHostAddress().startsWith(this.pattern)) { result = true; } } String[] splitPattern = this.pattern.split("/"); if (splitPattern.length > 1) { ip = splitPattern[0]; mask = splitPattern[1]; } else { ip = splitPattern[0]; } String ipConfig = ip2binary(ip); if (mask != null) { maskConfig = maskToBinaryString(mask); } ipClient = ip2binary(client.getHostAddress()); if (mask != null && ipConfig != null) { result = ipCheck(ipClient, ipConfig, maskConfig); } return result; } /** * @throws DepartmentSelectionCompileError * @see org.esupportail.helpdesk.domain.departmentSelection.conditions.AbstractCondition#checkInternal() */ @Override public void checkInternal() throws DepartmentSelectionCompileError { if (this.pattern == null) { throw new DepartmentSelectionCompileError("<ip> tags should have a 'pattern' attribute"); } } /** * @see java.lang.Object#toString() */ @Override public String toString() { return "<ip pattern=\"" + pattern + "\" />"; } /** * (left) pad a string with 0s up to 8 characters. * @param binaryString * @return a string. */ private String formatBinaryString(final String binaryString) { String result = binaryString; while (result.length() < CONST_8) { result = "0".concat(result); } return result; } /** * format an ip to a binary ip (ex: 255.255.255.0 to 11111111111111111111111100000000). * @param ip * @return String ip in a binary format */ private String ip2binary(final String ip) { String[] splited = ip.split("\\."); StringBuffer res = new StringBuffer(formatBinaryString(Integer.toBinaryString(Integer.parseInt(splited[0])))); for (int i = 1; i < splited.length; i++) { res.append(formatBinaryString(Integer.toBinaryString(Integer.parseInt(splited[i])))); } return res.toString(); } /** * convert a 'normal' mask to a binary format (ex: 255.255.255.0 to 11111111111111111111111100000000 or 24 * to 11111111111111111111111100000000). * @param mask the mask * @return String */ private String maskToBinaryString(final String mask) { StringBuffer binaryMask = new StringBuffer(); String[] splitedMask = mask.split("\\."); if (splitedMask.length <= 1) { for (int i = 0; i < Integer.parseInt(mask); i++) { binaryMask.append("1"); } //maskBinary = formatBinaryString(Integer.toBinaryString(Integer.parseInt(maskSplited[0]))); while (binaryMask.length() < CONST_32) { binaryMask.append("0"); } } else { binaryMask.append(formatBinaryString(Integer.toBinaryString(Integer.parseInt(splitedMask[0])))); for (int i = 1; i < splitedMask.length; i++) { binaryMask.append(formatBinaryString(Integer.toBinaryString(Integer.parseInt(splitedMask[i])))); } } return binaryMask.toString(); } /** * return true if the logic and between ipClient/mask and ipConfig/mask have the same result. * @param ipClient * @param ipConfig * @param mask * @return boolean true if logic and of ipClient/mask and ipConfig/mask have the same result */ private boolean ipCheck(final String ipClient, final String ipConfig, final String mask) { String clientNet = binaryAnd(ipClient, mask); String configNet = binaryAnd(ipConfig, mask); return clientNet.equals(configNet); } /** * own implementation of a binary 'AND'. * @param ip * @param mask * @return String the logic and of an ip and a mask */ private String binaryAnd(final String ip, final String mask) { char[] ipChar = ip.toCharArray(); char[] maskChar = mask.toCharArray(); StringBuffer result = new StringBuffer(); for (int i = 0; i < maskChar.length && i < ipChar.length; i++) { if (maskChar[i] == '1' && ipChar[i] == '1') { result.append("1"); } else { result.append("0"); } } return result.toString(); } /** * @see org.esupportail.helpdesk.domain.departmentSelection.conditions.Condition#getNodeType() */ @Override public String getNodeType() { return "ip"; } /** * @return the pattern */ public String getPattern() { return pattern; } }