/*
Tor Research Framework - easy to use tor client library/framework
Copyright (C) 2014 Dr Gareth Owen <drgowen@gmail.com>
www.ghowen.me / github.com/drgowen/tor-research-framework
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 3 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, see <http://www.gnu.org/licenses/>.
*/
package tor.util;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
import java.io.StringReader;
import java.util.Arrays;
import java.util.TreeMap;
/**
* Created by gho on 25/07/14.
*/
public class TorDocumentParser {
public TreeMap<String, String> map = new TreeMap<>();
// produces a map from a normal tor document, key/value pairs
// parses block BEGIN-ENDS correctly
// where same key appears twice, value is the concatenated values with | as a delimiter
// the order of the IPv4 accept/reject exit policies matters, and this order is destroyed by the parser
// we therefore substitute a synthesised key for accept/reject lines ("ipv4-policy" like the ipv6-policy key),
// and we prepend accept or reject to each line, using space as a second-level separator
// i.e. accept *:80|reject *:*
public final static String IPv4PolicyKey = "ipv4-policy";
private static TreeMap<String, String> keyReplacementMap;
public TreeMap<String, String> KeyReplacementMap() {
if (keyReplacementMap == null) {
keyReplacementMap = new TreeMap<>();
keyReplacementMap.put("accept", IPv4PolicyKey);
keyReplacementMap.put("reject", IPv4PolicyKey);
}
return keyReplacementMap;
}
public TorDocumentParser(String doc) throws IOException {
//String curKey = null;
//String curVal = null;
String lns[] = (String[]) IOUtils.readLines(new StringReader(doc)).toArray(new String[0]);
for (int i = 0; i < lns.length; i++) {
String ln = lns[i];
if (ln.equals(""))
continue;
String sp[] = ln.split(" ");
boolean nextBegin = lns.length > i + 1 ? lns[i + 1].contains("BEGIN") : false;
if (sp.length == 1 && nextBegin) { // single word and multiline
// see if next line contains begin
String key = sp[0], val = "";
i += 2;
for (; i < lns.length; i++) {
if (lns[i].contains("END")) {
break;
}
val += lns[i];
}
addItem(key, val);
} else if (sp.length == 1) { // single word but not multiline
addItem(sp[0], "");
} else { // regular line
addItem(sp[0], StringUtils.join(Arrays.copyOfRange(sp, 1, sp.length), " "));
}
}
// for (String k : map.keySet()) {
// System.out.println(k + "|||= " + map.get(k));
// }
}
public void addItem(String k, String v) {
// keys in the replacement map are replaced by the corresponding key in the map
// the original key is prepended to the value, separated by a space
if (KeyReplacementMap().containsKey(k)) {
addItem(KeyReplacementMap().get(k), k + " " + v);
} else {
if (!map.containsKey(k))
map.put(k, v);
else {
map.put(k, map.get(k) + "|" + v);
}
}
}
public String[] getArrayItem(String k) {
// keys in the replacement map are replaced by the corresponding key in the map
if (KeyReplacementMap().containsKey(k)) {
return getArrayItem(KeyReplacementMap().get(k));
} else {
String s[] = map.get(k).split("\\|");
if (s.length < 2)
throw new RuntimeException("error - not array item");
return s;
}
}
public String getItem(String k) {
// keys in the replacement map are replaced by the corresponding key in the map
if (KeyReplacementMap().containsKey(k))
return getItem(KeyReplacementMap().get(k));
else
return map.get(k);
}
}