package de.blinkt.openvpn; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.HashMap; import java.util.Vector; //! Openvpn Config FIle Parser, probably not 100% accurate but close enough // And rember, this is valid :) // -- // bar // public class ConfigParser { private HashMap> options = new HashMap>(); private void parseConfig(String filename) throws IOException, ConfigParseError { FileReader fr = new FileReader(filename); BufferedReader br =new BufferedReader(fr); int lineno=0; while (true){ String line = br.readLine(); if(line==null) break; lineno++; System.out.print("LINE:"); System.out.println(line); Vector args = parseline(line); if(args.size() ==0) continue; if(args.get(0).startsWith("--")) args.set(0, args.get(0).substring(2)); checkinlinefile(args,br); options.put(args.get(0), args); } } private void checkinlinefile(Vector args, BufferedReader br) throws IOException, ConfigParseError { String arg0 = args.get(0); // CHeck for if(arg0.startsWith("<") && arg0.endsWith(">")) { String argname = arg0.substring(1, arg0.length()-1); String inlinefile = ""; String endtag = String.format("",argname); do { String line = br.readLine(); if(line==null){ throw new ConfigParseError(String.format("No endtag for starttag <%s> found",argname,argname)); } if(line.equals(endtag)) break; else { inlinefile+=line; inlinefile+= "\n"; } } while(true); args.clear(); args.add(argname); args.add(inlinefile); } } enum linestate { initial, readin_single_quote , reading_quoted, reading_unquoted, done} private boolean space(char c) { // I really hope nobody is using zero bytes inside his/her config file // to sperate parameter but here we go: return Character.isSpace(c) || c == '\0'; } public class ConfigParseError extends Exception { private static final long serialVersionUID = -60L; public ConfigParseError(String msg) { super(msg); } } // adapted openvpn's parse function to java private Vector parseline(String line) throws ConfigParseError { Vector parameters = new Vector(); if (line.length()==0) return parameters; linestate state = linestate.initial; boolean backslash = false; char out=0; int pos=0; String currentarg=""; do { // Emulate the c parsing ... char in; if(pos < line.length()) in = line.charAt(pos); else in = '\0'; if (!backslash && in == '\\' && state != linestate.readin_single_quote) { backslash = true; } else { if (state == linestate.initial) { if (!space (in)) { if (in == ';' || in == '#') /* comment */ break; if (!backslash && in == '\"') state = linestate.reading_quoted; else if (!backslash && in == '\'') state = linestate.readin_single_quote; else { out = in; state = linestate.reading_unquoted; } } } else if (state == linestate.reading_unquoted) { if (!backslash && space (in)) state = linestate.done; else out = in; } else if (state == linestate.reading_quoted) { if (!backslash && in == '\"') state = linestate.done; else out = in; } else if (state == linestate.readin_single_quote) { if (in == '\'') state = linestate.done; else out = in; } if (state == linestate.done) { /* ASSERT (parm_len > 0); */ state = linestate.initial; parameters.add(currentarg); currentarg = ""; out =0; } if (backslash && out!=0) { if (!(out == '\\' || out == '\"' || space (out))) { throw new ConfigParseError("Options warning: Bad backslash ('\\') usage"); } } backslash = false; } /* store parameter character */ if (out!=0) { currentarg+=out; } } while (pos++ < line.length()); return parameters; } void convertProfile() throws ConfigParseError{ VpnProfile newprofile = new VpnProfile("converted Profile"); // Pull, client, tls-client if(options.containsKey("client") || options.containsKey("pull")) { newprofile.mUsePull=true; options.remove("pull"); options.remove("client"); } if(options.containsKey("secret")){ newprofile.mAuthenticationType=VpnProfile.TYPE_STATICKEYS; options.remove("secret"); } if(options.containsKey("redirect-gateway")) { options.remove("redirect-gateway"); newprofile.mUseDefaultRoute=true; } else { newprofile.mUseDefaultRoute=true; } Vector mode = options.get("mode"); if (mode != null){ options.remove("mode"); if(mode.size() != 2) throw new ConfigParseError("--mode has more than one parameter"); if(!mode.get(1).equals("p2p")) throw new ConfigParseError("Invalid mode for --mode specified"); } } }