/*********************************************************************** * * $CVSHeader$ * * This file is part of WebScarab, an Open Web Application Security * Project utility. For details, please see http://www.owasp.org/ * * Copyright (c) 2002 - 2004 Rogan Dawes * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Getting Source * ============== * * Source for this application is maintained at Sourceforge.net, a * repository for free software projects. * * For details, please see http://www.sourceforge.net/projects/owasp * */ /* * CharacterSetCalculator.java * * Created on 17 November 2003, 04:19 */ package org.owasp.webscarab.plugin.sessionid; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Map; import java.util.HashMap; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.util.logging.Logger; /** * * @author rdawes */ public class DefaultCalculator implements Calculator { private Pattern _pattern; private Map<SessionID, BigInteger> _cache = new HashMap<SessionID, BigInteger>(); Logger _logger = Logger.getLogger(this.getClass().getName()); private ArrayList<String> _chars = new ArrayList<String>(); private BigInteger _min = null; private BigInteger _max = null; /** Creates a new instance of DefaultCalculator */ public DefaultCalculator() { this("^(.+)$"); } public DefaultCalculator(String regex) { _pattern = Pattern.compile(regex); } public boolean add(SessionID id) { String value = id.getValue(); Matcher matcher = _pattern.matcher(value); if(matcher.matches() && matcher.groupCount()>=1) { value = matcher.group(1); return update(value); } else { System.err.println("value '" + value + "' did not match the pattern!"); return false; } } private boolean update(String value) { _logger.fine("Value is '" + value + "'"); boolean changed = false; for (int i=0; i<value.length(); i++) { char ch = value.charAt(value.length() - 1 - i); _logger.fine("Working on position " + i + ", character '" + ch + "'"); String set = null; if (_chars.size() > i) set = _chars.get(i); if (set == null) set = new String(); _logger.fine("Character set was '" + set + "'"); String updset = insertCharacter(set, ch); if (! updset.equals(set)) { _logger.fine("Character set is now '" + updset + "'"); reset(); if (_chars.size()>i) { _chars.set(i, updset); } else { _chars.add(i, updset); } changed = true; } } return changed; } private String insertCharacter(String set, char ch) { if (set.indexOf(ch) != -1) return set; char[] chars = set.toCharArray(); int insert = -Arrays.binarySearch(chars, ch) -1; StringBuffer buff = new StringBuffer(); buff.append(chars, 0, insert); buff.append(ch); buff.append(chars, insert, chars.length - insert); return buff.toString(); } public BigInteger calculate(SessionID id) { if (_cache.containsKey(id)) return _cache.get(id); String value = id.getValue(); Matcher matcher = _pattern.matcher(value); if(matcher.matches() && matcher.groupCount()>=1) { value = matcher.group(1); } else { return BigInteger.ZERO; } BigInteger total = BigInteger.ZERO; BigInteger max = BigInteger.ONE; int length = value.length(); _logger.fine("Calculating '" + value + "'"); for (int i=0; i<length; i++) { String charset = _chars.get(i); char ch = value.charAt(length - 1 - i); int pos = charset.indexOf(ch); _logger.fine("Working on position " + i + ", character '" + ch + "'"); _logger.fine("pos is " + pos); BigInteger val = new BigInteger(Integer.toString(pos)); total = total.add(val.multiply(max)); max = max.multiply(new BigInteger(Integer.toString(charset.length()))); } if (_max == null || _max.compareTo(total)<0) _max = total; if (_min == null || _min.compareTo(total)>0) _min = total; _cache.put(id, total); return total; } public void reset() { _cache.clear(); } public BigInteger max() { return _max; } public BigInteger min() { return _min; } }