package jpbx.core; /** * WebConfig service for jPBXlite * * @author pquiring * * Created : Sept 14, 2013 */ import java.io.*; import java.net.*; import java.util.*; import javaforce.*; import javaforce.service.*; public class WebConfig implements WebHandler { public static int http_port, https_port, sip_port; public static boolean hideAdmin, disableWebRTC; private static String dbVersion = "0.92"; private WebRTC webrtc; private Web http, https; public boolean start() { JFLog.log("Starting Web Server on port " + http_port); http = new Web(); http.start(this, http_port, false); if (new File(Paths.etc + "jpbx.key").exists()) { System.setProperty("javax.net.ssl.keyStore", Paths.etc + "jpbx.key"); System.setProperty("javax.net.ssl.keyStorePassword", "password"); JFLog.log("Starting Web Server on port " + https_port + " (secure)"); https = new Web(); https.start(this, https_port, true); if (!disableWebRTC) startWebRTC(); } return true; } private void startWebRTC() { webrtc = new WebRTC(); webrtc.init(); http.setWebSocketHandler(webrtc); if (https != null) https.setWebSocketHandler(webrtc); } public void stop() { if (http != null) { http.stop(); http = null; } if (https != null) { https.stop(); https = null; } if (webrtc != null) { // webrtc.stop(); webrtc = null; } } private String decode(String in) { try {return URLDecoder.decode(in, "UTF-8");} catch (Exception e) {} return ""; } public void doPost(WebRequest req, WebResponse res) { try {doRequest(req, res);} catch (Exception e) {JFLog.log(e);} } public void doGet(WebRequest req, WebResponse res) { try {doRequest(req, res);} catch (Exception e) {JFLog.log(e);} } private HashMap<String, byte[]> cache = new HashMap<String, byte[]>(); public void doStatic(WebRequest req, WebResponse res) throws Exception { String url = req.getURL(); if (url.equals("/favicon.ico")) { url = "/static/jpbxlite.ico"; } int idx = url.lastIndexOf('/'); String file = url.substring(idx+1); byte data[]; if (file.endsWith(".class")) { res.setStatus(404, "Not Found"); return; } if (file.endsWith(".css")) { res.setContentType("text/css"); } else if (file.endsWith(".js")) { res.setContentType("text/javascript"); } else if (file.endsWith(".png")) { res.setContentType("image/png"); } else if (file.endsWith(".ico")) { res.setContentType("image/x-icon"); } else if (file.endsWith(".txt")) { res.setContentType("text/plain"); } data = (byte[])cache.get(file); if (data != null) { res.getOutputStream().write(data); return; } data = JF.readAll(getClass().getClassLoader().getResourceAsStream(file)); if (data == null || data.length == 0) { res.setStatus(404, "Not Found"); return; } cache.put(file, data); res.getOutputStream().write(data); } private void writeHeaders(OutputStream os) throws Exception { StringBuilder html = new StringBuilder(); html.append("<html>"); html.append("<head>"); html.append(" <title>jPBXlite</title>"); html.append(" <link rel=stylesheet href='/static/style.css' type='text/css'>"); html.append(" <script type='text/javascript' src='/static/style.js'></script>"); html.append("</head>"); html.append("<body leftmargin=1 rightmargin=1 topmargin=1 bottommargin=1 vlink=ffffff link=ffffff alink=ffffff width=100% height=100%>"); os.write(html.toString().getBytes()); } public void doIndex(WebRequest req, WebResponse res) throws Exception { writeHeaders(res.getOutputStream()); StringBuilder html = new StringBuilder(); if (!hideAdmin) { html.append("<div style='float:right;'><a href='/login'>Admin</a></div>"); } html.append("<center>"); html.append("<img src='/static/logo.png'><br>"); html.append("<br>"); if (!disableWebRTC) { html.append("<t3>WebRTC Conferencing (experimental)</t3><br>"); html.append("<form action=webrtc1 method=get>"); html.append("Room Number:<input name=room size=10>"); html.append("<input type=submit value='Enter Room'> (2 per room)<br><br><br>"); html.append("</form>"); html.append("<t3>WebRTC Phone (experimental)</t3><br>"); html.append("<form action='https://" + req.getHost() + ":" + https_port + "/webrtc2' method=post>"); html.append("Your Number:<input name=user size=10><br>"); html.append("Password:<input type=password name=pass size=10><br>"); html.append("Dial Number:<input name=dial size=10><br>"); html.append("<input type=submit value='Make Call'>"); html.append("</form>"); } res.getOutputStream().write(html.toString().getBytes()); } public String ValidUser(String user, String passmd5) { SQL sql = new SQL(); if (!sql.connect(Service.jdbc)) return "Unable to connect to database"; String res = sql.select1value("SELECT passmd5 FROM users WHERE userid='" + user + "'"); sql.close(); if (res == null) return "Database not setup"; return (res.equalsIgnoreCase(passmd5) ? "ok" : "Invalid Login"); } public void doLogin(WebRequest req, WebResponse res) throws Exception { writeHeaders(res.getOutputStream()); String query = req.getQueryString(); String args[]; if (query != null) args = query.split("&"); else args = new String[0]; String user = "", pass = ""; for(int a=0;a<args.length;a++) { if (args[a].startsWith("user=")) user = args[a].substring(5); if (args[a].startsWith("pass=")) pass = args[a].substring(5); } String msg = ""; if ((user.length() > 0 && pass.length() > 0)) { //attempt login MD5 md5 = new MD5(); md5.init(); md5.add(pass.getBytes(),0,pass.length()); String passmd5 = new String(md5.byte2char(md5.done())); //check database msg = ValidUser(user, passmd5); if (msg.equals("ok")) { req.session.setAttribute("id", user); res.sendRedirect("/admin"); return; } } StringBuilder html = new StringBuilder(); html.append("<center>"); html.append("<div style='background-color: #dddddd; width: 320px;'>"); if (msg.length() > 0) { html.append("<font color=#ff0000>"); html.append(msg); html.append("<br></font>"); } html.append("<form action='/login'>"); html.append("Username : <input name=user><br>"); html.append("Password : <input type=password name=pass><br>"); html.append("<input type=submit value='Login'>"); html.append("</form>"); html.append("</div>"); html.append("<br><br>"); res.getOutputStream().write(html.toString().getBytes()); } public void doLogout(WebRequest req, WebResponse res) throws Exception { req.session.setAttribute("id", null); res.sendRedirect("/"); } private String doAdminPage(SQL sql, String args[]) { String verb = "", current = "", p1 = "", p2 = ""; for(int a=0;a<args.length;a++) { if (args[a].startsWith("verb=")) verb = args[a].substring(5); if (args[a].startsWith("current=")) current = args[a].substring(8); if (args[a].startsWith("p1=")) p1 = args[a].substring(3); if (args[a].startsWith("p2=")) p2 = args[a].substring(3); } String msg = ""; if (verb.equals("changepass")) { if (!p1.equals(p2)) { msg = "Passwords do not match!"; } else if (p1.length() < 5) { msg = "Password too short (min = 5)"; } else { MD5 md5 = new MD5(); md5.init(); md5.add(current.getBytes(),0,current.length()); String currentmd5 = new String(md5.byte2char(md5.done())); String storedmd5 = sql.select1value("SELECT passmd5 FROM users WHERE userid='admin'"); if ((storedmd5 == null) || (!storedmd5.equals(currentmd5))) { msg = "Incorrect current password"; } else { md5.init(); md5.add(p1.getBytes(),0,p1.length()); String passmd5 = new String(md5.byte2char(md5.done())); if (!sql.execute("UPDATE users SET passmd5=" + sql.quote(passmd5) + " WHERE userid='admin'")) { msg = "Unable to change password (DB error)"; } else { msg = "Password changed"; } } } } StringBuilder html = new StringBuilder(); html.append("<center>"); html.append("Change Admin Password:<br>"); html.append("<div style='background-color: #dddddd; width: 320px;'>"); if (msg.length() > 0) { html.append("<font color=#ff0000>"); html.append(msg + "<br>"); html.append("</font>"); } html.append(form("core", "admin")); html.append("<input type=hidden name=verb value='changepass'>"); html.append("<table>"); html.append("<tr><td nowrap>Current Password: </td><td> <input type=password name=current></td></tr>"); html.append("<tr><td nowrap>New Password : </td><td> <input type=password name=p1></td></tr>"); html.append("<tr><td nowrap>Confirm Password : </td><td> <input type=password name=p2></td></tr>"); html.append("</table>"); html.append("<input type=submit value=Change>"); html.append("</form>"); html.append("</div>"); return html.toString(); } private String doBlankPage(SQL sql, String args[]) { return "Please select an option on the left."; } private String doConfPage(SQL sql, String args[]) { return "Conferences are special IVRs. To create a conference, create a new IVR and load the preset \"Conference\".<br>\n" + "To create a video conference select the \"Video Conference\" preset.<br>\n" + "Then change the $adminpass and $userpass variables for the admin and user pass codes.<br>\n"; } private String doExtsPage(SQL sql, String args[]) { String verb = "", ext = "", editext = "", cloneStart = "", cloneCount = "", display = "", cid = "", pass = "", msg = "", sure = "", vm = "", vmpass = ""; for(int a=0;a<args.length;a++) { int x = args[a].indexOf("=") + 1; if (args[a].startsWith("verb=")) verb = args[a].substring(x); if (args[a].startsWith("ext=")) ext = args[a].substring(x); if (args[a].startsWith("editext=")) editext = args[a].substring(x); if (args[a].startsWith("cloneStart=")) cloneStart = args[a].substring(x); if (args[a].startsWith("cloneCount=")) cloneCount = args[a].substring(x); if (args[a].startsWith("display=")) display = args[a].substring(x); if (args[a].startsWith("cid=")) cid = args[a].substring(x); if (args[a].startsWith("pass=")) pass = args[a].substring(x); if (args[a].startsWith("sure=")) sure = args[a].substring(x); if (args[a].startsWith("vm=")) vm = args[a].substring(x); if (args[a].startsWith("vmpass=")) vmpass = args[a].substring(x); } ext = numbersOnly(ext); cid = numbersOnly(cid); display = convertString(display); vmpass = numbersOnly(vmpass); if (verb.equals("del")) { if (sure.equalsIgnoreCase("on")) { if (sql.execute("DELETE FROM exts WHERE ext=" + sql.quote(ext))) { if (!sql.execute("DELETE FROM extopts WHERE ext=" + sql.quote(ext))) { msg = "Failed to delete extension options"; } } else { msg = "Failed to delete extension"; } if (msg.length() == 0) { msg = "Extension deleted"; } } else { msg = "Please confirm delete action"; } ext = ""; } if (verb.equals("view")) { editext = ext; String exts[] = sql.select1row("SELECT display,cid,pass FROM exts WHERE ext=" + sql.quote(ext)); if (exts != null) { display = exts[0]; cid = exts[1]; pass = exts[2]; vm = sql.select1value("SELECT value FROM extopts WHERE ext=" + sql.quote(ext) + " AND id='vm'"); if (vm == null) vm = "false"; vmpass = sql.select1value("SELECT value FROM extopts WHERE ext=" + sql.quote(ext) + " AND id='vmpass'"); if (vmpass == null) vmpass = ""; } } if (verb.equals("add") || verb.equals("edit")) { if (ext.length() == 0) { msg = "Invalid extension number"; } else { String isivr = sql.select1value("SELECT ext FROM ivrs WHERE ext=" + sql.quote(ext)); if ((isivr != null) && (isivr.equals(ext))) { msg = "IVR already exists with that number"; } } if (display.length() == 0) { msg = "Invalid display name"; } if (pass.length() == 0) { msg = "Invalid password"; } if (msg.length() > 0) { if (verb.equals("add")) verb = ""; else verb = "view"; } } if (verb.equals("add")) { if (!sql.execute("INSERT INTO exts (ext, display, cid, pass) VALUES (" + sql.quote(ext) + "," + sql.quote(display) + "," + sql.quote(cid) + "," + sql.quote(pass) + ")")) { msg = "Failed to add : " + sql.getLastException(); } else if (!sql.execute("INSERT INTO extopts (ext, id, value) VALUES (" + sql.quote(ext) + ",'vm'," + sql.quote( (vm.equalsIgnoreCase("on") ? "true" : "false") ) + ")")) { msg = "Unable to add voicemail option"; } else if (!sql.execute("INSERT INTO extopts (ext, id, value) VALUES (" + sql.quote(ext) + ",'vmpass'," + sql.quote(vmpass) + ")")) { msg = "Unable to add voicemail password"; } if (msg.length() == 0) { msg = "Extension added"; ext = ""; display = ""; cid = ""; pass = ""; vm = ""; vmpass = ""; } } if (verb.equals("edit")) { if (!sql.execute("UPDATE exts SET ext=" + sql.quote(ext) + ",display=" + sql.quote(display) + ",cid=" + sql.quote(cid) + ",pass=" + sql.quote(pass) + " WHERE ext=" + sql.quote(editext))) { msg = "Failed to edit : " + sql.getLastException(); } else if (!sql.execute("UPDATE extopts SET ext=" + sql.quote(ext) + ",value=" + sql.quote( (vm.equalsIgnoreCase("on") ? "true" : "false") ) + " WHERE id='vm' AND ext=" + sql.quote(editext))) { msg = "Unable to edit voicemail option"; } else if (!sql.execute("UPDATE extopts SET ext=" + sql.quote(ext) + ",value=" + sql.quote(vmpass) + " WHERE id='vmpass' AND ext=" + sql.quote(editext))) { msg = "Unable to edit voicemail password"; } if (msg.length() == 0) { msg = "Extension edited"; ext = ""; display = ""; cid = ""; pass = ""; vm = ""; vmpass = ""; } else { verb = "view"; } } if (verb.equals("clone")) { verb = ""; String exts[] = sql.select1row("SELECT cid,pass FROM exts WHERE ext=" + sql.quote(ext)); cid = exts[0]; pass = exts[1]; vm = sql.select1value("SELECT value FROM extopts WHERE ext=" + sql.quote(ext) + " AND id='vm'"); if (vm == null) vm = "false"; vmpass = sql.select1value("SELECT value FROM extopts WHERE ext=" + sql.quote(ext) + " AND id='vmpass'"); if (vmpass == null) vmpass = ""; try { int start = Integer.valueOf(cloneStart); int count = Integer.valueOf(cloneCount); if (count <=0 || count > 1000) throw new Exception("max 1000 clones"); int added = 0; for(int idx=start;count > 0;count--,idx++) { ext = "" + idx; display = "" + idx; msg = ""; if (!sql.execute("INSERT INTO exts (ext, display, cid, pass) VALUES (" + sql.quote(ext) + "," + sql.quote(display) + "," + sql.quote(cid) + "," + sql.quote(pass) + ")")) { msg = "Failed to add"; } else if (!sql.execute("INSERT INTO extopts (ext, id, value) VALUES (" + sql.quote(ext) + ",'vm'," + sql.quote(vm) + ")")) { msg = "Unable to add voicemail option"; } else if (!sql.execute("INSERT INTO extopts (ext, id, value) VALUES (" + sql.quote(ext) + ",'vmpass'," + sql.quote(vmpass) + ")")) { msg = "Unable to add voicemail password"; } if (msg.length() == 0) added++; } msg = "Cloning complete (" + added + " extensions added)"; } catch (Exception e) { msg = "Cloning failed:" + e.toString(); } ext = ""; display = ""; cid = ""; pass = ""; vm = ""; vmpass = ""; } StringBuilder html = new StringBuilder(); html.append("<table height=100%>"); html.append("<tr><td width=100%>"); if (msg.length() > 0) html.append("<font color=#ff0000>" + msg + "</font><br>"); if (verb.equals("view")) { html.append(form("core", "exts")); html.append("<input type=hidden name=verb value=del><input type=hidden name=ext value=" + sql.quote(ext) + ">"); html.append("<input type=submit value='Delete Extension'> <input type=checkbox name=sure>I'm Sure</form>"); } html.append(form("core", "exts")); if (verb.equals("cloneForm")) { html.append("<input type=hidden name=verb value=clone>"); html.append("<table>"); html.append("<tr><td>Extension #:</td><td><input name=ext value=" + sql.quote(ext) + " readonly></td></tr>"); html.append("<tr><td>Start:</td><td><input name=cloneStart></td></tr>"); html.append("<tr><td>Count:</td><td><input name=cloneCount></td></tr>"); html.append("<tr><td colspan=2>NOTE : Existing extension in clone range may be altered!</td></tr>"); html.append("</table>"); html.append("<input type=submit value=Clone>"); } else { html.append("<input type=hidden name=verb value=" + (verb.equals("view") ? "edit" : "add") + ">"); if (verb.equals("view")) html.append("<input type=hidden name=editext value=" + sql.quote(editext) + ">"); html.append("<table>"); html.append("<tr><td>Extension #:</td><td><input name=ext value=" + sql.quote(ext) + "></td><td>"); if (verb.equals("view")) { html.append(link("core", "exts", "verb=cloneForm&ext=" + editext, "Clone")); } html.append("</td></tr>"); html.append("<tr><td>Display Name:</td><td><input name=display value=" + sql.quote(display) + "></td><td>(usually same as extension #)</td></tr>"); html.append("<tr><td>Outbound Caller ID #:</td><td><input name=cid value=" + sql.quote(cid) + "></td><td>(optional) (used if call sent to trunk)</td></tr>"); html.append("<tr><td>SIP Password:</td><td><input name=pass value=" + sql.quote(pass) + "></td></tr>"); html.append("<tr><td>VoiceMail:</td><td><input type=checkbox name=vm " + (vm.equals("true") ? "checked" : "") + "></td></tr>"); html.append("<tr><td>VM Password:</td><td><input name=vmpass value=" + sql.quote(vmpass) + "></td></tr>"); html.append("</table>"); html.append("<input type=submit value=" + (verb.equals("view") ? "Edit" : "Add") + ">"); } html.append("</form>"); html.append("</td><td width=2 bgcolor=#000000></td><td width=180>"); html.append("<div class=menuitem>" + link("core", "exts", "", "Add New") + "</div>"); String exts[][] = sql.select("SELECT ext,display FROM exts ORDER BY ext"); if (exts != null) { for(int a=0;a<exts.length;a++) { html.append("<div class=menuitem>" + link("core", "exts", "verb=view&ext=" + exts[a][0], exts[a][1] + "<" + exts[a][0] + ">") + "</div>"); } } html.append("</td></tr>"); html.append("</table>"); return html.toString(); } private String doInRoutesPage(SQL sql, String args[]) { StringBuilder html = new StringBuilder(); String verb = "", route = "", cid = "", did = "", dest = "", msg = "", editroute= "", sure = ""; for(int a=0;a<args.length;a++) { int x = args[a].indexOf("=") + 1; if (args[a].startsWith("verb=")) verb = args[a].substring(x); if (args[a].startsWith("route=")) route = args[a].substring(x); if (args[a].startsWith("editroute=")) editroute = args[a].substring(x); if (args[a].startsWith("cid=")) cid = args[a].substring(x); if (args[a].startsWith("did=")) did = args[a].substring(x); if (args[a].startsWith("dest=")) dest = args[a].substring(x); if (args[a].startsWith("sure=")) sure = args[a].substring(x); } cid = numbersOnly(cid); did = numbersOnly(did); dest = numbersOnly(dest); if (route.length() == 0) verb = ""; if (verb.equals("del")) { if (sure.equalsIgnoreCase("on")) { if (sql.execute("DELETE FROM inroutes WHERE route=" + sql.quote(route))) { msg = "Route deleted"; } else { msg = "Failed to delete"; } } else { msg = "Please confirm delete action"; } route = ""; } if (verb.equals("view")) { editroute = route; String routes[] = sql.select1row("SELECT cid,did,dest FROM inroutes WHERE route=" + sql.quote(route)); if (routes != null) { cid = routes[0]; did = routes[1]; dest = routes[2]; } } if (verb.equals("add") || verb.equals("edit")) { if ((cid.length() == 0) && (did.length() == 0)) { msg = "You must define DID and/or CID"; if (verb.equals("add")) verb = ""; else verb = "view"; } if (dest.length() == 0) { msg = "Destination must be defined"; if (verb.equals("add")) verb = ""; else verb = "view"; } } if (verb.equals("add")) { if (sql.execute("INSERT INTO inroutes (route, cid, did, dest) VALUES (" + sql.quote(route) + "," + sql.quote(cid) + "," + sql.quote(did) + "," + sql.quote(dest) + ")")) { msg = "Route added"; route = ""; cid = ""; did = ""; dest = ""; } else { msg = "Failed to add:" + sql.getLastException(); } } if (verb.equals("edit")) { if (sql.execute("UPDATE inroutes SET route=" + sql.quote(route) + ",cid=" + sql.quote(cid) + ",did=" + sql.quote(did) + ",dest=" + sql.quote(dest) + " WHERE route=" + sql.quote(editroute))) { msg = "Route edited"; route = ""; cid = ""; did = ""; dest = ""; } else { msg = "Failed to edit:" + sql.getLastException(); verb = "view"; } } html.append("<table height=100%>"); html.append("<tr><td width=100%>"); if (msg.length() > 0) { html.append("<font color=#ff0000>" + msg + "</font><br>"); } if (verb.equals("view")) { html.append(form("core", "inroutes")); html.append("<input type=hidden name=verb value=del><input type=hidden name=route value=" + sql.quote(route) + "><input type=submit value='Delete route'>"); html.append("<input type=checkbox name=sure>I'm Sure</form>"); } html.append(form("core", "inroutes")); html.append("<input type=hidden name=verb value=" + (verb.equals("view") ? "edit" : "add") + ">"); if (verb.equals("view")) { html.append("<input type=hidden name=editroute value=" + sql.quote(editroute) + ">"); } html.append("<table>"); html.append("<tr><td> Route Name: </td><td> <input name=route value=" + sql.quote(route) + "</td></tr>"); html.append("<tr><td> Dialed # (DID): </td><td> <input name=did value=" + sql.quote(did) + "></td><td>(optional)</td></tr>"); html.append("<tr><td> Caller # (CID): </td><td> <input name=cid value=" + sql.quote(cid) + "></td><td>(optional)</td></tr>"); html.append("<tr><td> Destination #: </td><td> <input name=dest value=" + sql.quote(dest) + "></td><td>(Extension, IVR, etc.)</tr>"); html.append("<tr><td> <input type=submit value=" + (verb.equals("view") ? "Edit" : "Add") + "></td></tr>"); html.append("</table>"); html.append("</form>"); html.append("</td><td width=2 bgcolor=#000000></td><td width=180>"); html.append("<div class=menuitem>" + link("core", "inroutes", "", "Add New") + "</div>"); String routes[][] = sql.select("SELECT route, did, cid FROM inroutes ORDER BY route"); if (routes != null) { for(int a=0;a<routes.length;a++) { if (routes[a][1].length() == 0) routes[a][1] = "any DID"; if (routes[a][2].length() == 0) routes[a][2] = "any CID"; html.append("<div class=menuitem>" + link("core", "inroutes", "verb=view&route=" + routes[a][0], "<" + routes[a][0] + ">" + routes[a][1] + "/" + routes[a][2]) + "</div>"); } } html.append("</td></tr></table>"); return html.toString(); } private String doIVRPage(SQL sql, String args[]) { String verb = "", ext = "", editext = "", display = "", script = "", sure = "", msg = ""; for(int a=0;a<args.length;a++) { int x = args[a].indexOf("=") + 1; if (args[a].startsWith("verb=")) verb = args[a].substring(x); if (args[a].startsWith("ext=")) ext = args[a].substring(x); if (args[a].startsWith("display=")) display = args[a].substring(x); if (args[a].startsWith("script=")) script = args[a].substring(x); if (args[a].startsWith("editext=")) editext = args[a].substring(x); if (args[a].startsWith("sure=")) sure = args[a].substring(x); } ext = numbersOnly(ext); if (verb.equals("del")) { if (sure.equalsIgnoreCase("on")) { if (!sql.execute("DELETE FROM ivrs WHERE ext=" + sql.quote(ext))) { msg = "Failed to delete IVR"; } if (msg.length() == 0) { msg = "IVR deleted"; } } else { msg = "Please confirm delete action"; } ext = ""; } if (verb.equals("view")) { editext = ext; display = sql.select1value("SELECT display FROM ivrs WHERE ext=" + sql.quote(ext)); script = sql.select1value("SELECT script FROM ivrs WHERE ext=" + sql.quote(ext)); } if (verb.equals("add") || verb.equals("edit")) { if (ext.length() == 0) { msg = "Invalid IVR number"; } else { String isext = sql.select1value("SELECT ext FROM exts WHERE ext=" + sql.quote(ext)); if ((isext != null) && (isext.equals(ext))) { msg = "Extension already exists with that number"; } } if (display.length() == 0) { msg = "Invalid display name"; } if (msg.length() > 0) { if (verb.equals("add")) verb = ""; else verb = "view"; } } if (verb.equals("add")) { if (!sql.execute("INSERT INTO ivrs (ext, display, script) VALUES (" + sql.quote(ext) + "," + sql.quote(display) + "," + sql.quote(script) + ")")) { msg = "Failed to add"; } if (msg.length() == 0) { msg = "IVR added"; ext = ""; display = ""; script = ""; } } if (verb.equals("edit")) { if (!sql.execute("UPDATE ivrs SET ext=" + sql.quote(ext) + ",display=" + sql.quote(display) + ",script=" + sql.quote(script) + " WHERE ext=" + sql.quote(editext))) { msg = "Failed to edit : " + sql.getLastException(); verb = "view"; } if (msg.length() == 0) { msg = "IVR edited"; ext = ""; display = ""; script = ""; } } StringBuilder html = new StringBuilder(); html.append("<table height=100%>"); html.append("<tr><td width=100%>"); if (msg.length() > 0) { html.append("<font color=#ff0000>" + msg + "</font><br>"); } if (verb.equals("view")) { html.append(form("core", "ivrs")); html.append("<input type=hidden name=verb value=del><input type=hidden name=ext value=" + sql.quote(ext)); html.append("><input type=submit value='Delete IVR'>" + "<input type=checkbox name=sure>I'm Sure</form>"); } html.append(form("core", "ivrs")); html.append("<input type=hidden name=verb value=" + (verb.equals("view") ? "edit" : "add") + ">"); if (verb.equals("view")) { html.append("<input type=hidden name=editext value=" + sql.quote(editext) + ">"); } html.append("<table>"); html.append("<tr><td>IVR #:</td><td><input name=ext value=" + sql.quote(ext) + ">"); html.append("</td></tr>"); html.append("<tr><td>Name:</td><td><input name=display value=" + sql.quote(display) + "></td></tr>"); html.append("<tr><td>Script:</td><td><textarea id=script name=script cols=40 rows=20>" + convertString(script) + "</textarea></td><td><a href=\"javascript:showHelp('ivr');\">Help</a><br>"); html.append("Presets:<select id=preset><option>-none-</option><option>Conference</option><option>Video Conference</option></select> <a href=\"javascript:load_preset();\">Load</a></td></tr>"); html.append("</table>"); html.append("<input type=submit value=" + (verb.equals("view") ? "Edit" : "Add") + ">"); html.append("</form>"); html.append("</td><td width=2 bgcolor=#000000></td><td width=180>"); html.append("<div class=menuitem>" + link("core", "ivrs", "", "Add New") + "</div>"); String ivrs[][] = sql.select("SELECT ext,display FROM ivrs ORDER BY ext"); if (ivrs != null) { for(int a=0;a<ivrs.length;a++) { html.append("<div class=menuitem>" + link("core", "ivrs", "verb=view&ext=" + ivrs[a][0], ivrs[a][1] + "<" + ivrs[a][0] + ">") + "</div>"); } } html.append("</td></tr>"); html.append("</table>"); return html.toString(); } private String doQueuesPage(SQL sql, String args[]) { String verb = "", ext = "", editext = "", display = "", agents = "", sure = "", msg = "", message = ""; for(int a=0;a<args.length;a++) { int x = args[a].indexOf("=") + 1; if (args[a].startsWith("verb=")) verb = args[a].substring(x); if (args[a].startsWith("ext=")) ext = args[a].substring(x); if (args[a].startsWith("display=")) display = args[a].substring(x); if (args[a].startsWith("agents=")) agents = convertString(args[a].substring(x)).replaceAll("\r\n", ","); if (args[a].startsWith("message=")) message = args[a].substring(x); if (args[a].startsWith("editext=")) editext = args[a].substring(x); if (args[a].startsWith("sure=")) sure = args[a].substring(x); } if (message.length() == 0) message = "acd-wait-for-agent"; ext = numbersOnly(ext); if (verb.equals("del")) { if (sure.equalsIgnoreCase("on")) { if (!sql.execute("DELETE FROM queues WHERE ext=" + sql.quote(ext))) { msg = "Failed to delete queue"; } if (msg.length() == 0) { msg = "Queue deleted"; } } else { msg = "Please confirm delete action"; } ext = ""; } if (verb.equals("view")) { editext = ext; display = sql.select1value("SELECT display FROM queues WHERE ext=" + sql.quote(ext)); agents = sql.select1value("SELECT agents FROM queues WHERE ext=" + sql.quote(ext)); message = sql.select1value("SELECT message FROM queues WHERE ext=" + sql.quote(ext)); } if (verb.equals("add") || verb.equals("edit")) { if (ext.length() == 0) { msg = "Invalid Queue number"; } else { String isext = sql.select1value("SELECT ext FROM exts WHERE ext=" + sql.quote(ext)); if ((isext != null) && (isext.equals(ext))) { msg = "Extension already exists with that number"; } } if (display.length() == 0) { msg = "Invalid display name"; } if (msg.length() > 0) { if (verb.equals("add")) verb = ""; else verb = "view"; } } if (verb.equals("add")) { if (!sql.execute("INSERT INTO queues (ext, display, agents, message) VALUES (" + sql.quote(ext) + "," + sql.quote(display) + "," + sql.quote(agents) + "," + sql.quote(message) + ")")) { msg = "Failed to add"; } if (msg.length() == 0) { msg = "Queue added"; ext = ""; display = ""; agents = ""; } } if (verb.equals("edit")) { if (!sql.execute("UPDATE queues SET ext=" + sql.quote(ext) + ",display=" + sql.quote(display) + ",agents=" + sql.quote(agents) + ",message=" + sql.quote(message) + " WHERE ext=" + sql.quote(editext))) { msg = "Failed to edit : " + sql.getLastException(); verb = "view"; } if (msg.length() == 0) { msg = "Queue edited"; ext = ""; display = ""; agents = ""; } } StringBuilder html = new StringBuilder(); html.append("<table height=100%>"); html.append("<tr><td width=100%>"); if (msg.length() > 0) { html.append("<font color=#ff0000>" + msg + "</font><br>"); } if (verb.equals("view")) { html.append(form("core", "queues")); html.append("<input type=hidden name=verb value=del><input type=hidden name=ext value=" + sql.quote(ext)); html.append("><input type=submit value='Delete Queue'>" + "<input type=checkbox name=sure>I'm Sure</form>"); } html.append(form("core", "queues")); html.append("<input type=hidden name=verb value=" + (verb.equals("view") ? "edit" : "add") + ">"); if (verb.equals("view")) { html.append("<input type=hidden name=editext value=" + sql.quote(editext) + ">"); } html.append("<table>"); html.append("<tr><td>Queue #:</td><td><input name=ext value=" + sql.quote(ext) + ">"); html.append("</td></tr>"); html.append("<tr><td>Name:</td><td><input name=display value=" + sql.quote(display) + "></td></tr>"); html.append("<tr><td>Agents:</td><td><textarea id=agents name=agents cols=40 rows=20>" + convertString(agents).replaceAll(",", "\r\n") + "</textarea> (list agents one per line)</td></tr>"); html.append("<tr><td>Member Join Message:</td><td>"); ArrayList<String> wavFiles = new ArrayList<String>(); try { File f = new File(Paths.sounds + Paths.lang + "/"); File fs[] = f.listFiles(); if (fs != null) { Arrays.sort(fs); for(int a=0;a<fs.length;a++) { String file = fs[a].getName(); if (!file.endsWith(".wav")) continue; file = file.substring(0, file.length() - 4); if (!file.equals("acd-wait-for-agent") && isBuiltinSound(file)) continue; wavFiles.add(file); } } } catch (Exception e2) { html.append(e2.toString()); } html.append(select("message", message, wavFiles.toArray(new String[0]))); html.append(" (use " + link("core", "msgs", "", "Messages") + " page to upload new files)</td></tr>"); html.append("</table>"); html.append("<input type=submit value=" + (verb.equals("view") ? "Edit" : "Add") + ">"); html.append("</form>"); html.append("</td><td width=2 bgcolor=#000000></td><td width=180>"); html.append("<div class=menuitem>" + link("core", "queues", "", "Add New") + "</div>"); String queues[][] = sql.select("SELECT ext,display FROM queues ORDER BY ext"); if (queues != null) { for(int a=0;a<queues.length;a++) { html.append("<div class=menuitem>" + link("core", "queues", "verb=view&ext=" + queues[a][0], queues[a][1] + "<" + queues[a][0] + ">") + "</div>"); } } html.append("</td></tr>"); html.append("</table>"); return html.toString(); } private String doMsgsPage(SQL sql, String args[], WebRequest req) { String verb = "", file = "", oldfile = "", newfile = "", sure = "", msg= ""; for(int a=0;a<args.length;a++) { int x = args[a].indexOf("=") + 1; if (args[a].startsWith("verb=")) verb = args[a].substring(x); if (args[a].startsWith("file=")) file = decode(args[a].substring(x)); if (args[a].startsWith("oldfile=")) oldfile = decode(args[a].substring(x)); if (args[a].startsWith("newfile=")) newfile = decode(args[a].substring(x)); if (args[a].startsWith("sure=")) sure = args[a].substring(x); } if ( (file.indexOf("..") != -1) || (file.indexOf("/") != -1) || (file.indexOf("\\") != -1) ) { return "ERROR : invalid filename."; } if (verb.equals("del")) { if (sure.equalsIgnoreCase("on")) { if (isBuiltinSound(file)) { msg = "Can not delete built-in message"; } else { try { File f = new File(Paths.sounds + Paths.lang + "/" + file + ".wav"); f.delete(); msg = "Deleted file : " + f.getName(); } catch (Exception e1) { msg = "Unable to delete file"; } } } else { msg = "Please confirm delete action"; } } if (verb.equals("upload")) { try { if (WebUpload.isMultipartContent(req)) { WebUpload webUpload = new WebUpload(); WebUpload.WebFile files[] = webUpload.parseRequest(req); JFLog.log("files=" + files.length); for(int a=0;a<files.length;a++) { String fileName = files[a].name; JFLog.log("filename=" + fileName); if (!fileName.toLowerCase().endsWith(".wav")) { msg += "Not a wav:" + fileName + "<br>"; continue; } String dirName = Paths.sounds + Paths.lang + "/"; try { File saveTo = new File(dirName + fileName); files[a].write(saveTo); msg += "Uploaded:" + fileName + "<br>"; } catch (Exception e3) { msg += "Upload failed:" + fileName + ":" + e3 + "<br>"; } } } else { msg += "No upload data found."; } } catch (Exception e) { msg += e; } } if (verb.equals("rename")) { verb = ""; if (isBuiltinSound(oldfile) || isBuiltinSound(newfile)) { msg = "Can not rename build-in sound"; } else { File oldFile = new File(Paths.sounds + Paths.lang + "/" + oldfile + ".wav"); File newFile = new File(Paths.sounds + Paths.lang + "/" + newfile + ".wav"); oldFile.renameTo(newFile); msg = "File renamed"; } } StringBuilder html = new StringBuilder(); html.append("<table height=100%>"); html.append("<tr><td width=100%>"); if (msg.length() > 0) html.append("<font color=#ff0000>" + msg + "</font><br>"); if (verb.equals("view")) { html.append(form("core", "msgs")); html.append("<input type=hidden name=verb value=del><input type=hidden name=file value=" + sql.quote(file)); html.append("><input type=submit value='Delete Message'>" + "<input type=checkbox name=sure>I'm Sure</form>"); } if (verb.equals("renameForm")) { html.append(form("core", "msgs")); html.append("Not implemented Yet!<br>"); html.append("<input type=hidden name=verb value=rename>"); html.append("<table>"); html.append("<tr><td>Old Filename:</td><td><input name=oldfile value=" + sql.quote(oldfile) + " readonly></td></tr>"); html.append("<tr><td>New Filename:</td><td><input name=newfile></td></tr>"); html.append("</table>"); html.append("<input type=submit value=Rename>"); html.append("</form>"); } else if (verb.equals("view")) { html.append("<table>"); html.append("<tr><td>Filename:</td><td>" + file); html.append(link("core", "msgs", "verb=renameForm&oldfile=" + file, "Rename")); html.append("</td></tr>"); html.append("</table>"); } else { html.append(formUpload("core", "msgs", "verb=upload")); html.append("<table>"); html.append("<tr><td>Filename:</td><td><input type=file name=file></td><td><input type=submit value='Upload'></td></tr>"); html.append("</table>"); html.append("</form>"); html.append("Wav files must be 8000Hz, mono, 16bit in PCM format.<br>"); } html.append("</td><td width=2 bgcolor=#000000></td><td width=180>"); html.append("<div class=menuitem>" + link("core", "msgs", "", "Add New") + "</div>"); try { File f = new File(Paths.sounds + Paths.lang + "/"); File fs[] = f.listFiles(); if (fs != null) { Arrays.sort(fs); for(int a=0;a<fs.length;a++) { file = fs[a].getName(); if (!file.endsWith(".wav")) continue; file = file.substring(0, file.length() - 4); html.append("<div class=menuitem>" + link("core", "msgs", "verb=view&file=" + file, file + "<" + (isBuiltinSound(file) ? "builtin" : "custom") + ">") + "</div>"); } } } catch (Exception e2) { html.append(e2.toString()); } html.append("</td></tr>"); html.append("</table>"); return html.toString(); } private String doOutRoutesPage(SQL sql, String args[]) { String verb = "", routetable = "", route = "", priority = "", cid = "", patterns = "", trunks = "", msg = "", editroute= "", t1 = "", t2 = "", t3 = "", t4 = "", sure = ""; for(int a=0;a<args.length;a++) { int x = args[a].indexOf("=") + 1; if (args[a].startsWith("verb=")) verb = args[a].substring(x); if (args[a].startsWith("routetable=")) routetable = args[a].substring(x); if (args[a].startsWith("route=")) route = args[a].substring(x); if (args[a].startsWith("priority=")) priority = args[a].substring(x); if (args[a].startsWith("editroute=")) editroute = args[a].substring(x); if (args[a].startsWith("cid=")) cid = args[a].substring(x); if (args[a].startsWith("patterns=")) patterns = args[a].substring(x); if (args[a].startsWith("t1=")) t1 = args[a].substring(x); if (args[a].startsWith("t2=")) t2 = args[a].substring(x); if (args[a].startsWith("t3=")) t3 = args[a].substring(x); if (args[a].startsWith("t4=")) t4 = args[a].substring(x); if (args[a].startsWith("sure=")) sure = args[a].substring(x); } cid = numbersOnly(cid); trunks = t1; if (t2.length() > 0) {if (trunks.length() > 0) trunks += ":"; trunks += t2;} if (t3.length() > 0) {if (trunks.length() > 0) trunks += ":"; trunks += t3;} if (t4.length() > 0) {if (trunks.length() > 0) trunks += ":"; trunks += t4;} priority = numbersOnly(priority); if (priority.length() == 0) priority = "0"; if (routetable.length() == 0) verb = ""; if (verb.equals("deltable")) { if (sql.execute("DELETE FROM outroutetables WHERE routetable=" + sql.quote(routetable))) { sql.execute("DELETE FROM outroutes WHERE routetable=" + sql.quote(routetable)); msg = "Table deleted"; } else { msg = "Failed to delete table"; } routetable = ""; } if (verb.equals("addtable")) { if (sql.execute("INSERT INTO outroutetables (routetable) VALUES (" + sql.quote(routetable) + ")")) { msg = "Table added"; } else { msg = "Failed to add table"; } } if (route.length() == 0) verb = ""; if (verb.equals("del")) { if (sure.equalsIgnoreCase("on")) { if (sql.execute("DELETE FROM outroutes WHERE routetable=" + sql.quote(routetable) + " AND route=" + sql.quote(route))) { msg = "Route deleted"; } else { msg = "Failed to delete"; } } else { msg = "Please confirm delete action"; } route = ""; } if (verb.equals("view")) { editroute = route; String routes[] = sql.select1row("SELECT priority,cid,patterns,trunks FROM outroutes WHERE routetable=" + sql.quote(routetable) + " AND route=" + sql.quote(route)); if (routes != null) { priority = routes[0]; cid = routes[1]; patterns = routes[2]; trunks = routes[3]; String lns[] = trunks.split(":"); if (lns.length > 0) t1 = lns[0]; if (lns.length > 1) t2 = lns[1]; if (lns.length > 2) t3 = lns[2]; if (lns.length > 3) t4 = lns[3]; } } if (verb.equals("add")) { patterns = convertString(patterns).replaceAll("\r\n", ":"); patterns = patternsOnly(patterns); if (sql.execute("INSERT INTO outroutes (routetable, route, priority, cid, patterns, trunks) VALUES (" + sql.quote(routetable) + "," + sql.quote(route) + "," + priority + "," + sql.quote(cid) + "," + sql.quote(patterns) + "," + sql.quote(trunks) + ")")) { msg = "Route added"; route = ""; priority = ""; cid = ""; patterns = ""; trunks = ""; t1 = ""; t2 = ""; t3 = ""; t4 = ""; } else { msg = "Failed to add"; } } if (verb.equals("edit")) { patterns = convertString(patterns).replaceAll("\r\n", ":"); patterns = patternsOnly(patterns); if (sql.execute("UPDATE outroutes SET route=" + sql.quote(route) + ",priority=" + sql.quote(priority) + ",cid=" + sql.quote(cid) + ",patterns=" + sql.quote(patterns) + ",trunks=" + sql.quote(trunks) + " WHERE routetable=" + sql.quote(routetable) + " AND route=" + sql.quote(editroute))) { msg = "Route edited"; route = ""; priority = ""; cid = ""; patterns = ""; t1 = ""; t2 = ""; t3 = ""; t4 = ""; } else { msg = "Failed to edit"; verb = "view"; } } String list[] = sql.select1col("SELECT trunk FROM trunks"); StringBuilder html = new StringBuilder(); html.append("<table height=100%>"); html.append("<tr><td width=100%>"); html.append("<div class=table>"); html.append("<div class=menucat>Routing Tables</div>"); String tables[] = sql.select1col("SELECT routetable FROM outroutetables"); if (tables != null) { for(int a=0;a<tables.length;a++) { if (routetable.equals(tables[a])) { html.append("<div class=menuitemselected>"); } else { html.append("<div class=menuitem>"); } html.append(link("core", "outroutes", "routetable=" + tables[a], tables[a]) + "</div>"); } } html.append(form("core", "outroutes") + "<input name=routetable><input type=hidden name=verb value=addtable><input type=submit value='Add Table'></form><br>"); html.append(form("core", "outroutes") + "<input name=routetable><input type=hidden name=verb value=deltable><input type=submit value='Delete Table'></form>"); html.append("</div>"); html.append("<hr>"); if (routetable.length() > 0) { if (msg.length() > 0) html.append("<font color=#ff0000>" + msg + "</font><br>"); if (verb.equals("view")) { html.append(form("core", "outroutes") + "<input type=hidden name=routetable value=" + routetable); html.append("><input type=hidden name=verb value=del><input type=hidden name=route value=" + sql.quote(route) + "><input type=submit value='Delete route'>"); html.append("<input type=checkbox name=sure>I'm Sure</form>"); } html.append(form("core", "outroutes")); html.append("<input type=hidden name=routetable value=" + sql.quote(routetable) + ">"); html.append("<input type=hidden name=verb value=" + (verb.equals("view") ? "edit" : "add") + ">"); if (verb.equals("view")) { html.append("<input type=hidden name=editroute value=" + sql.quote(editroute) + ">"); } html.append("<table>"); html.append("<tr><td> Route Name: </td><td> <input name=route value=" + sql.quote(route) + "></td></tr>"); html.append("<tr><td> Priority: </td><td> <input name=priority value=" + sql.quote(priority) + "></td></tr>"); html.append("<tr><td> Default Caller ID: </td><td> <input name=cid value=" + sql.quote(cid) + "></td><td>(optional)</td></tr>"); html.append("<tr><td> Dial Patterns: </td><td> <textarea name=patterns cols=20 rows=10>"); String lns[] = patterns.split(":"); for(int a=0;a<lns.length;a++) html.append(lns[a]); html.append("</textarea>"); html.append("</td><td>"); html.append("If dialed # matches any patterns then this route is used to send call to trunks listed.<br>"); html.append("If this route is used then dialed # will be modified before sending to trunk.<br>"); html.append("<pre>"); html.append(" #=matches exact digit (0-9)\r\n"); html.append(" X=matches 0-9\r\n"); html.append(" Z=matches 1-9\r\n"); html.append(" N=matches 2-9\r\n"); html.append(" x|y = removes 'x' if 'xy' matches\r\n"); html.append(" x+y = adds 'x' if 'y' matches\r\n"); html.append(" .=wildcard (last char only)\r\n"); html.append("</pre>"); html.append("</td></tr>"); html.append("<tr><td> Trunks: </td><td>"); html.append(select("t1", t1, list) + "<br>"); html.append(select("t2", t2, list) + "<br>"); html.append(select("t3", t3, list) + "<br>"); html.append(select("t4", t4, list) + "<br>"); html.append("</td></tr>"); html.append("<tr><td> <input type=submit value=" + (verb.equals("view") ? "Edit" : "Add") + "></td></tr>"); html.append("</table>"); html.append("</form>"); } html.append("</td><td width=2 bgcolor=#000000></td><td width=180>"); if (routetable.length() == 0) { html.append("<div class=menuitem>Select a Routing Table</div>"); } else { html.append("<div class=menuitem>" + link("core", "outroutes", "routetable=" + routetable, "Add New") + "</div>"); String routes[] = sql.select1col("SELECT route FROM outroutes WHERE routetable=" + sql.quote(routetable) + " ORDER BY priority"); if (routes != null) { for(int a=0;a<routes.length;a++) { html.append("<div class=menuitem>" + link("core", "outroutes", "routetable=" + routetable + "&verb=view&route=" + routes[a], "<" + routes[a] + ">") + "</div>"); } } } html.append("</td></tr></table>"); return html.toString(); } public String getCfg(String cfg[][], String id) { for(int a=0;a<cfg.length;a++) { if (cfg[a][0].equals(id)) return cfg[a][1]; } return ""; } public String checked(String in) { if (in.equals("true")) return "checked"; return ""; } private String doSettingsPage(SQL sql, String args[], WebRequest req) { String verb = "", port = "", msg = "", anon = "", route = "", rtpmin = "", rtpmax = "", videoCodecs = ""; String relayAudio = "", relayVideo = "", moh = ""; String http = "", https = "", hideAdmin = "", disableWebRTC = ""; String valid = "", dname = ""; for(int a=0;a<args.length;a++) { int x = args[a].indexOf("=") + 1; if (args[a].startsWith("verb=")) verb = args[a].substring(x); if (args[a].startsWith("port=")) port = args[a].substring(x); if (args[a].startsWith("anon=")) anon = args[a].substring(x); if (args[a].startsWith("route=")) route = args[a].substring(x); if (args[a].startsWith("rtpmin=")) rtpmin = args[a].substring(x); if (args[a].startsWith("rtpmax=")) rtpmax = args[a].substring(x); if (args[a].startsWith("videoCodecs=")) videoCodecs = decode(args[a].substring(x).toUpperCase()); if (args[a].startsWith("relayAudio=")) relayAudio = args[a].substring(x); if (args[a].startsWith("relayVideo=")) relayVideo = args[a].substring(x); if (args[a].startsWith("moh=")) moh = decode(args[a].substring(x)); if (args[a].startsWith("http=")) http = args[a].substring(x); if (args[a].startsWith("https=")) https = args[a].substring(x); if (args[a].startsWith("hideAdmin=")) hideAdmin = args[a].substring(x); if (args[a].startsWith("disableWebRTC=")) disableWebRTC = args[a].substring(x); if (args[a].startsWith("valid=")) valid = args[a].substring(x); if (args[a].startsWith("dname=")) dname = decode(args[a].substring(x)); } StringBuilder html = new StringBuilder(); html.append("<font color=#ff0000>"); html.append(msg); html.append("</font>"); html.append("General Settings:<br>"); html.append("<div class=table>"); if (verb.equals("save")) { if (anon.equals("on")) anon = "true"; else anon = "false"; if (route.equals("on")) route = "true"; else route = "false"; if (relayAudio.equals("on")) relayAudio = "true"; else relayAudio = "false"; if (relayVideo.equals("on")) relayVideo = "true"; else relayVideo = "false"; if (hideAdmin.equals("on")) hideAdmin = "true"; else hideAdmin = "false"; if (disableWebRTC.equals("on")) disableWebRTC = "true"; else disableWebRTC = "false"; int irtpmin, irtpmax; try { irtpmin = Integer.valueOf(rtpmin); if (irtpmin % 2 == 1) irtpmin++; //must be even irtpmax = Integer.valueOf(rtpmax); if (irtpmax % 2 == 1) irtpmax++; //must be even if ((irtpmin < 1024) || (irtpmin > 65534-1000)) irtpmin = 32768; if ((irtpmax < 1024) || (irtpmax > 65535)) irtpmax = 65535; if ((irtpmin > irtpmax) || (irtpmax - irtpmin < 1000)) { irtpmin = 32768; irtpmax = 65535; } } catch (Exception e) { JFLog.log(e); irtpmin = 32768; irtpmax = 65535; } sql.execute("UPDATE config SET value=" + sql.quote(port) + " WHERE id='port'"); sql.execute("UPDATE config SET value=" + sql.quote(anon) + " WHERE id='anon'"); sql.execute("UPDATE config SET value=" + sql.quote(route) + " WHERE id='route'"); sql.execute("UPDATE config SET value=" + sql.quote("" + irtpmin) + " WHERE id='rtpmin'"); sql.execute("UPDATE config SET value=" + sql.quote("" + irtpmax) + " WHERE id='rtpmax'"); sql.execute("UPDATE config SET value=" + sql.quote(videoCodecs) + " WHERE id='videoCodecs'"); sql.execute("UPDATE config SET value=" + sql.quote(relayAudio) + " WHERE id='relayAudio'"); sql.execute("UPDATE config SET value=" + sql.quote(relayVideo) + " WHERE id='relayVideo'"); sql.execute("UPDATE config SET value=" + sql.quote(moh) + " WHERE id='moh'"); sql.execute("UPDATE config SET value=" + sql.quote(http) + " WHERE id='http'"); sql.execute("UPDATE config SET value=" + sql.quote(https) + " WHERE id='https'"); sql.execute("UPDATE config SET value=" + sql.quote(hideAdmin) + " WHERE id='hideAdmin'"); sql.execute("UPDATE config SET value=" + sql.quote(disableWebRTC) + " WHERE id='disableWebRTC'"); msg = "Settings saved"; } //NOTE : The -debug option is important to prevent KeyTool from executing System.exit() if (verb.equals("sslSelf")) { if (KeyMgmt.keytool(new String[] { "-genkey", "-debug", "-alias", "jpbxlite", "-keypass", "password", "-storepass", "password", "-keystore", Paths.etc + "jpbx.key", "-validity", valid, "-dname", dname, "-keyalg" , "RSA", "-keysize", "2048" })) { msg = "Generated self-signed SSL Certificate"; } else { msg = "KeyTool Error"; } } String cfg[][] = sql.select("SELECT id,value FROM config"); if (cfg == null) { return "Database error"; } html.append("<font color=#ff0000>" + msg + "</font><br>"); html.append(form("core", "settings")); html.append("<input type=hidden name='verb' value='save'>"); html.append("SIP Port : <input name=port value=" + getCfg(cfg, "port") + "><br>"); html.append("RTP Port Min : <input name=rtpmin value=" + getCfg(cfg, "rtpmin") + "> (1024-64534) (default:32768)<br>"); html.append("RTP Port Max : <input name=rtpmax value=" + getCfg(cfg, "rtpmax") + "> (2023-65535) (default:65535)<br>"); html.append("RTP Port Range must include at least 1000 ports and start on an even port number.<br>"); html.append("<input type=checkbox name=anon " + checked(getCfg(cfg, "anon")) + "> Anonymous Inbound Calls (allows calls from any source to extensions, voicemail, IVRs, etc.)<br>"); html.append("<input type=checkbox name=route " + checked(getCfg(cfg, "route")) + "> Route Calls (route calls from one trunk to another) [not implemented yet]<br>"); html.append("Video Conference Codecs : <input name=videoCodecs value=" + getCfg(cfg, "videoCodecs") + "> [comma list : H263,H263-1998,H263-2000,H264,VP8]<br>"); html.append("<input type=checkbox name=relayAudio " + checked(getCfg(cfg, "relayAudio")) + "> Relay Audio Media (recommended)<br>"); html.append("<input type=checkbox name=relayVideo " + checked(getCfg(cfg, "relayVideo")) + "> Relay Video Media (optional)<br>"); html.append("Music on Hold : "); ArrayList<String> wavFiles = new ArrayList<String>(); try { File f = new File(Paths.sounds + Paths.lang + "/"); File fs[] = f.listFiles(); if (fs != null) { Arrays.sort(fs); for(int a=0;a<fs.length;a++) { String file = fs[a].getName(); if (!file.endsWith(".wav")) continue; file = file.substring(0, file.length() - 4); if (isBuiltinSound(file)) continue; wavFiles.add(file); } } } catch (Exception e2) { html.append(e2.toString()); } html.append(select("moh", getCfg(cfg, "moh"), wavFiles.toArray(new String[0]))); html.append(" (use " + link("core", "msgs", "", "Messages") + " page to upload new files)<br>"); html.append("Web HTTP Port : <input name=http value=" + getCfg(cfg, "http") + "><br>"); html.append("Web HTTPS Port : <input name=https value=" + getCfg(cfg, "https") + "><br>"); html.append("<input type=checkbox name=hideAdmin " + checked(getCfg(cfg, "hideAdmin")) + "> Hide Admin Link on Home Page<br>"); html.append("<input type=checkbox name=disableWebRTC " + checked(getCfg(cfg, "disableWebRTC")) + "> Disable WebRTC support<br>"); html.append("<br>"); html.append("<input type=submit value='Save'>"); html.append("</form>"); html.append("<br><br><br>"); html.append("Secure Web SSL Cerificate:<br><br>"); html.append("Generate self-signed Key/Certificate Pair:<br>"); html.append(form("core", "settings")); html.append("dname:<input name=dname value='CN=" + req.getHost() + ", OU=jpbxlite, O=JavaForce, C=CA' size=50><br>"); html.append("valid(days):<input name=valid value='3650' size=10><br>"); html.append("<input type=hidden name='verb' value='sslSelf'>"); html.append("<input type=submit value='Generate'>"); html.append("</form><br><br>"); html.append("All options on this page will not take effect until the server is restarted.<br>"); html.append("</div>"); return html.toString(); } private String doStatusPage(SQL sql, String args[]) { String verb = "", msg = ""; for(int a=0;a<args.length;a++) { int x = args[a].indexOf("=") + 1; if (args[a].startsWith("verb=")) verb = args[a].substring(x); } if (verb.equals("initdb") || verb.equals("upgradedb")) { String version; version = sql.select1value("SELECT value FROM config WHERE id='version'"); if (version == null) version = "0.0"; Float fversion = Float.valueOf(version); //setup init DB (ignore errors -- it is repeatable) if (fversion == 0.91) { sql.execute("DROP TABLE queues"); //test } sql.execute("CREATE TABLE svcplugins (jar VARCHAR(32), cls VARCHAR(32), UNIQUE (jar, cls))"); sql.execute("INSERT INTO svcplugins (jar, cls) VALUES ('extensions.jar', 'core.Extensions')"); sql.execute("INSERT INTO svcplugins (jar, cls) VALUES ('trunks.jar', 'core.Trunks')"); sql.execute("INSERT INTO svcplugins (jar, cls) VALUES ('voicemail.jar', 'core.VoiceMail')"); sql.execute("INSERT INTO svcplugins (jar, cls) VALUES ('ivrs.jar', 'core.IVR')"); sql.execute("INSERT INTO svcplugins (jar, cls) VALUES ('queues.jar', 'core.Queues')"); sql.execute("CREATE TABLE webplugins (plugin VARCHAR(16), pg VARCHAR(16), cat VARCHAR(32), display VARCHAR(32), UNIQUE (plugin, pg))"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'status', 'General', 'System Status')"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'admin', 'General', 'Administrator')"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'exts', 'General', 'Extensions')"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'ivrs', 'General', 'IVR')"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'conf', 'General', 'Conference')"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'msgs', 'General', 'Messsages')"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'trunks', 'General', 'Trunks')"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'settings', 'General', 'Settings')"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'outroutes', 'Routing', 'Outbound Routes')"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'inroutes', 'Routing', 'Inbound Routes')"); sql.execute("INSERT INTO webplugins (plugin, pg, cat, display) VALUES ('core', 'queues', 'General', 'Queues')"); sql.execute("CREATE TABLE webpluginusers (plugin VARCHAR(16), pg VARCHAR(16), userid VARCHAR(16), UNIQUE (plugin, pg, userid))"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'status', 'admin')"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'admin', 'admin')"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'exts', 'admin')"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'ivrs', 'admin')"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'conf', 'admin')"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'msgs', 'admin')"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'trunks', 'admin')"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'settings', 'admin')"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'outroutes', 'admin')"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'inroutes', 'admin')"); sql.execute("INSERT INTO webpluginusers (plugin, pg, userid) VALUES ('core', 'queues', 'admin')"); sql.execute("CREATE TABLE config (id VARCHAR(32) NOT NULL UNIQUE, value VARCHAR(256))"); sql.execute("DELETE FROM config WHERE id='version'"); sql.execute("INSERT INTO config (id, value) VALUES ('version', '" + dbVersion + "')"); sql.execute("INSERT INTO config (id, value) VALUES ('port', '5060')"); sql.execute("INSERT INTO config (id, value) VALUES ('rtpmin', '32768')"); sql.execute("INSERT INTO config (id, value) VALUES ('rtpmax', '65535')"); sql.execute("INSERT INTO config (id, value) VALUES ('anon', 'false')"); sql.execute("INSERT INTO config (id, value) VALUES ('route', 'false')"); sql.execute("INSERT INTO config (id, value) VALUES ('defaultoutroutetable', 'default')"); sql.execute("INSERT INTO config (id, value) VALUES ('binpath', 'invalid')"); //each time the service starts it will set this value sql.execute("INSERT INTO config (id, value) VALUES ('videoCodecs', 'H264,VP8')"); sql.execute("INSERT INTO config (id, value) VALUES ('relayAudio', 'true')"); sql.execute("INSERT INTO config (id, value) VALUES ('relayVideo', 'true')"); sql.execute("INSERT INTO config (id, value) VALUES ('moh', '')"); sql.execute("INSERT INTO config (id, value) VALUES ('http', '80')"); sql.execute("INSERT INTO config (id, value) VALUES ('https', '443')"); sql.execute("INSERT INTO config (id, value) VALUES ('hideAdmin', 'false')"); sql.execute("INSERT INTO config (id, value) VALUES ('disableWebRTC', 'false')"); sql.execute("CREATE TABLE notices (msg VARCHAR(64) NOT NULL, plugin VARCHAR(16), pg VARCHAR(16))"); sql.execute("CREATE TABLE exts (ext VARCHAR(16) NOT NULL UNIQUE, display VARCHAR(64) NOT NULL, cid VARCHAR(16), pass VARCHAR(16) NOT NULL)"); sql.execute("CREATE TABLE extopts (ext VARCHAR(16) NOT NULL, id VARCHAR(16) NOT NULL, value VARCHAR(32), UNIQUE (ext, id))"); //voicemail, routetable, block1, block011, etc. sql.execute("CREATE TABLE trunks (trunk VARCHAR(16) NOT NULL UNIQUE, host VARCHAR(255) NOT NULL, cid VARCHAR(16) NOT NULL DEFAULT '0000000000', register VARCHAR(512), outrules CLOB, inrules CLOB, routetable VARCHAR(16) NOT NULL DEFAULT 'default')"); sql.execute("CREATE TABLE outroutetables (routetable VARCHAR(16) NOT NULL UNIQUE)"); sql.execute("INSERT INTO outroutetables (routetable) VALUES ('default')"); //can not be deleted/edited sql.execute("CREATE TABLE outroutes (routetable VARCHAR(16) NOT NULL, route VARCHAR(16) NOT NULL, cid VARCHAR(16), patterns CLOB NOT NULL, trunks CLOB NOT NULL, priority INT NOT NULL, UNIQUE (routetable, route))"); sql.execute("CREATE TABLE inroutes (route VARCHAR(16) NOT NULL UNIQUE, did VARCHAR(16), cid VARCHAR(16), dest VARCHAR(16))"); sql.execute("CREATE TABLE ivrs (ext VARCHAR(16) NOT NULL UNIQUE, display VARCHAR(64) NOT NULL, script CLOB NOT NULL)"); sql.execute("CREATE TABLE queues (ext VARCHAR(16) NOT NULL UNIQUE, display VARCHAR(64) NOT NULL, agents CLOB NOT NULL, message VARCHAR(256) NOT NULL)"); if (verb.equals("initdb")) msg = "Database created"; else msg = "Database upgraded"; } StringBuilder html = new StringBuilder(); if (msg.length() > 0) html.append("<font color=#ff0000>" + msg + "</font>"); html.append("<div class=table>"); html.append("<div class=notice>Notices</div>"); String res = sql.select1value("SELECT value FROM config WHERE id='version'"); if (res == null) { html.append("<div class=noticeitem>"); html.append(link("core", "status", "verb=initdb", "Database not initialized")); html.append("</div>"); } else if (!res.equals(dbVersion)) { html.append("<div class=noticeitem>"); html.append(link("core", "status", "verb=upgradedb", "Database upgrade required")); html.append("</div>"); } res = sql.select1value("SELECT passmd5 FROM users WHERE userid='admin'"); if ((res == null) || (res.equals("21232f297a57a5a743894a0e4a801fc3"))) { html.append("<div class=noticeitem>"); html.append(link("core", "admin", "", "Default Admin Password in use")); html.append("</div>"); } String notices[][] = sql.select("SELECT msg, plugin, pg FROM notices"); if (notices != null) { for(int a=0;a<notices.length;a++) { html.append("<div class=noticeitem>"); if ((notices[a][1] == null) || (notices[a][2] == null)) { html.append(notices[a][0]); } else { html.append(link(notices[a][1], notices[a][2], "", notices[a][0])); } html.append("</div>"); } } html.append("</div>"); return html.toString(); } private String doTrunksPage(SQL sql, String args[]) { String verb = "", trunk = "", cid = "", host = "", register = "", msg = "", outrules = "", inrules = "", edittrunk= "", sure = ""; for(int a=0;a<args.length;a++) { int x = args[a].indexOf("=") + 1; if (args[a].startsWith("verb=")) verb = args[a].substring(x); if (args[a].startsWith("trunk=")) trunk = args[a].substring(x); if (args[a].startsWith("edittrunk=")) edittrunk = args[a].substring(x); if (args[a].startsWith("cid=")) cid = args[a].substring(x); if (args[a].startsWith("host=")) host = args[a].substring(x); if (args[a].startsWith("register=")) register = args[a].substring(x); if (args[a].startsWith("outrules=")) outrules = args[a].substring(x); if (args[a].startsWith("inrules=")) inrules = args[a].substring(x); if (args[a].startsWith("sure=")) sure = args[a].substring(x); } cid = numbersOnly(cid); if (trunk.length() == 0) verb = ""; if (verb.equals("del")) { if (sure.equalsIgnoreCase("on")) { if (sql.execute("DELETE FROM trunks WHERE trunk=" + sql.quote(trunk))) { msg = "Trunk deleted"; } else { msg = "Failed to delete"; } } else { msg = "Please confirm delete action"; } trunk = ""; } if (verb.equals("view")) { edittrunk = trunk; String trunks[] = sql.select1row("SELECT host,cid,outrules,inrules,register FROM trunks WHERE trunk=" + sql.quote(trunk)); if (trunks != null) { host = trunks[0]; cid = trunks[1]; outrules = trunks[2]; inrules = trunks[3]; register = trunks[4]; } } if (verb.equals("add")) { outrules = convertString(outrules).replaceAll("\r\n", ":"); outrules = patternsOnly(outrules); inrules = convertString(inrules).replaceAll("\r\n", ":"); inrules = patternsOnly(inrules); register = convertString(register); if (sql.execute("INSERT INTO trunks (trunk, host, cid, outrules, inrules, register) VALUES (" + sql.quote(trunk) + "," + sql.quote(host) + "," + sql.quote(cid) + "," + sql.quote(outrules) + "," + sql.quote(inrules) + "," + sql.quote(register) + ")")) { msg = "Trunk added"; trunk = ""; host = ""; cid = ""; register = ""; outrules = ""; inrules = ""; } else { msg = "Failed to add:" + sql.getLastException(); } } if (verb.equals("edit")) { outrules = convertString(outrules).replaceAll("\r\n", ":"); outrules = patternsOnly(outrules); inrules = convertString(inrules).replaceAll("\r\n", ":"); inrules = patternsOnly(inrules); register = convertString(register); if (sql.execute("UPDATE trunks SET trunk=" + sql.quote(trunk) + ",host=" + sql.quote(host) + ",cid=" + sql.quote(cid) + ",outrules=" + sql.quote(outrules) + ",inrules=" + sql.quote(inrules) + ",register=" + sql.quote(register) + " WHERE trunk=" + sql.quote(edittrunk))) { msg = "Trunk edited"; trunk = ""; host = ""; cid = ""; register = ""; outrules = ""; inrules = ""; } else { msg = "Failed to edit:" + sql.getLastException(); verb = "view"; } } StringBuilder html = new StringBuilder(); html.append("<table height=100%>"); html.append("<tr><td width=100%>"); if (msg.length() > 0) html.append("<font color=#ff0000>" + msg + "</font><br>"); if (verb.equals("view")) { html.append(form("core", "trunks") + "<input type=hidden name=verb value=del><input type=hidden name=trunk value=" + sql.quote(trunk)); html.append("><input type=submit value='Delete Trunk'>" + "<input type=checkbox name=sure>I'm Sure</form>"); } html.append(form("core", "trunks")); html.append("<input type=hidden name=verb value=" + (verb.equals("view") ? "edit" : "add") + ">"); if (verb.equals("view")) html.append("<input type=hidden name=edittrunk value=" + sql.quote(edittrunk) + ">"); html.append("<table>"); html.append("<tr><td> Trunk: </td><td> <input name=trunk value=" + sql.quote(trunk) + "</td></tr>"); html.append("<tr><td> Host: </td><td> <input name=host value=" + sql.quote(host) + "></td><td>domain_or_ip[:port] (default port = 5060)</td></tr>"); html.append("<tr><td nowrap> Override Caller ID: </td><td> <input name=cid value=" + sql.quote(cid) + "></td><td>(optional)</td></tr>"); html.append("<tr><td> Register String: </td><td> <input name=register value=" + sql.quote(register) + "></td><td>(optional) [user:pass@host/did]</td></tr>"); html.append("<tr><td> Dial Out Rules: </td><td> <textarea name=outrules cols=20 rows=10>"); String lns[] = outrules.split(":"); for(int a=0;a<lns.length;a++) html.append(lns[a]); html.append("</textarea>"); html.append("</td><td>"); html.append("(optional)<br>"); html.append("Used to modify # dialed.<br>"); html.append("If no matches are found the # is dialed as is.<br>"); html.append("<pre>"); html.append(" #=matches exact digit (0-9)\r\n"); html.append(" X=matches 0-9\r\n"); html.append(" Z=matches 1-9\r\n"); html.append(" N=matches 2-9\r\n"); html.append(" x|y = removes 'x' if 'xy' matches\r\n"); html.append(" x+y = adds 'x' if 'y' matches\r\n"); html.append(" .=wildcard (last char only)\r\n"); html.append("</pre>"); html.append("</td></tr>"); html.append("<tr><td> Dial In Rules: </td><td> <textarea name=inrules class=aligntop cols=20 rows=10>"); lns = inrules.split(":"); for(int a=0;a<lns.length;a++) html.append(lns[a]); html.append("</textarea>"); html.append("</td><td>"); html.append("(optional) [not implemented yet]<br>"); html.append("<pre>"); html.append(" #=matches exact digit (0-9)\r\n"); html.append(" X=matches 0-9\r\n"); html.append(" Z=matches 1-9\r\n"); html.append(" N=matches 2-9\r\n"); html.append(" x|y = removes 'x' if 'xy' matches\r\n"); html.append(" x+y = adds 'x' if 'y' matches\r\n"); html.append(" .=wildcard (last char only)\r\n"); html.append("</pre>"); html.append("</td></tr>"); html.append("<tr><td> <input type=submit value=" + (verb.equals("view") ? "Edit" : "Add") + "></td></tr>"); html.append("</table>"); html.append("</form>"); html.append("</td><td width=2 bgcolor=#000000></td><td width=180>"); html.append("<div class=menuitem>" + link("core", "trunks", "", "Add New") + "</div>"); String trunks[] = sql.select1col("SELECT trunk FROM trunks"); if (trunks != null) { for(int a=0;a<trunks.length;a++) { html.append("<div class=menuitem>" + link("core", "trunks", "verb=view&trunk=" + trunks[a], "<" + trunks[a] + ">") + "</div>"); } } html.append("</td></tr></table>"); return html.toString(); } private String getPluginPage(String plugin, String pg, SQL sql, String args[], WebRequest req) { //currently plugin is only "core" - the idea was to allow other plugins - not likely if (!plugin.equals("core")) return "Plugin does not exist"; if (pg.equals("blank")) { return doBlankPage(sql, args); } else if (pg.equals("admin")) { return doAdminPage(sql, args); } else if (pg.equals("conf")) { return doConfPage(sql, args); } else if (pg.equals("exts")) { return doExtsPage(sql, args); } else if (pg.equals("inroutes")) { return doInRoutesPage(sql, args); } else if (pg.equals("ivrs")) { return doIVRPage(sql, args); } else if (pg.equals("msgs")) { return doMsgsPage(sql, args, req); } else if (pg.equals("outroutes")) { return doOutRoutesPage(sql, args); } else if (pg.equals("settings")) { return doSettingsPage(sql, args, req); } else if (pg.equals("status")) { return doStatusPage(sql, args); } else if (pg.equals("trunks")) { return doTrunksPage(sql, args); } else if (pg.equals("queues")) { return doQueuesPage(sql, args); } return "Page does not exist"; } public void doAdmin(WebRequest req, WebResponse res) throws Exception { writeHeaders(res.getOutputStream()); StringBuilder html = new StringBuilder(); String id = (String)req.session.getAttribute("id"); if (id == null) { res.sendRedirect("/login"); return; } String args[] = req.getQueryString().split("&"); SQL sql = new SQL(); if (!sql.connect(Service.jdbc)) { res.write("SQL connection failed".getBytes()); return; } String plugin = "core"; String pg; if (isAdmin(id)) { pg = "status"; } else { pg = "blank"; //TODO : voicemail for normal users ??? } for(int a=0;a<args.length;a++) { if (args[a].startsWith("plugin=")) plugin = args[a].substring(7); if (args[a].startsWith("pluginpg=")) pg = args[a].substring(9); } if (!isAllowed(sql, id, plugin, pg)) { redir(res, "core", "blank"); return; } html.append("<div style='overflow: auto;'>"); html.append("<table border=0 width=100% height=100% cellpadding=0 cellspacing=0>"); html.append("<tr height=64><td width=100% colspan=2><a href='http://jpbxlite.sourceforge.net'><img border=0 src=/static/img/logo.png></a>"); html.append("<a href='/logout' style='float:right;'>Logout</a></td></tr>"); html.append("<tr><td style='width: 180px; vertical-align:top;'>"); html.append(listPlugins(sql, id, plugin, pg)); html.append("</td><td style='vertical-align:top; width: 100%;'>"); html.append("<div style='border-top: 2px solid #000000; border-left: 2px solid #000000; height: 100%;'>"); html.append(getPluginPage(plugin, pg, sql, args, req)); html.append("</div>"); html.append("</td></tr>"); html.append("</table>"); html.append("</div>"); html.append("<div style='position: absolute; display: none; top: 0px; left: 0px; width: 100%; height: 100%; overflow: auto;' id='help'>"); html.append("<table width=100% height=100%>"); html.append("<tr height=10%><td colspan=3 class='transparent'> </td></tr>"); html.append("<tr width=100% height=80%>"); html.append(" <td width=10% class='transparent'> </td>"); html.append(" <td width=80% style='background-color: #ffffff; border: 5px; border-color: #000000; border-style: solid;'>"); html.append(" <div style='float: right;'><a href=\"javascript:hide('help');\">Close</a></div>"); html.append(" <div style='overflow: auto;' id='helpcontent'></div>"); html.append(" </td>"); html.append(" <td width=10% class='transparent'> </td>"); html.append("</tr>"); html.append("<tr height=10%><td colspan=3 class='transparent'> </td></tr>"); html.append("</table>"); html.append("</div>"); res.getOutputStream().write(html.toString().getBytes()); sql.close(); } private void noCache(WebResponse res) { res.addHeader("Cache-Control: no-cache, no-store, must-revalidate"); res.addHeader("Pragma: no-cache"); res.addHeader("Expires: 0"); } public void doRequest(WebRequest req, WebResponse res) throws Exception { String url = req.getURL(); if (url.startsWith("/static/") || url.equals("/favicon.ico")) { noCache(res); //for development doStatic(req, res); } else if (url.equals("/")) { doIndex(req, res); } else if (url.startsWith("/login")) { noCache(res); doLogin(req, res); } else if (url.startsWith("/logout")) { noCache(res); doLogout(req, res); } else if (url.startsWith("/admin")) { noCache(res); doAdmin(req, res); } if (!disableWebRTC) { if (url.startsWith("/webrtc1")) { noCache(res); webrtc.doWebRTC1(req, res); } else if (url.startsWith("/webrtc2")) { noCache(res); webrtc.doWebRTC2(req, res); } } } //Core API public String listPlugins(SQL sql, String id, String plugin, String pluginpg) { String res[][] = sql.select("SELECT webplugins.plugin,webplugins.pg,webplugins.display,webplugins.cat FROM webplugins JOIN webpluginusers" + " ON webplugins.plugin = webpluginusers.plugin AND webplugins.pg = webpluginusers.pg" + " WHERE webpluginusers.userid=" + sql.quote(id) + " OR webpluginusers.userid='*'" + " ORDER BY webplugins.cat"); if (res == null) { if (isAdmin(id)) { //allow init setup res = new String[1][4]; res[0][0] = "core"; res[0][1] = "status"; res[0][2] = "System Status (init)"; res[0][3] = "General"; } else { return ""; } } StringBuffer list = new StringBuffer(); String lastCat = ""; // list.append("length=" + res.length); for(int a=0;a<res.length;a++) { if (!res[a][3].equals(lastCat)) { lastCat = res[a][3]; list.append("<div class=menucat>" + res[a][3] + "</div>"); } if (plugin.equalsIgnoreCase(res[a][0]) && pluginpg.equalsIgnoreCase(res[a][1])) { list.append("<div class=menuitemselected>"); } else { list.append("<div class=menuitem>"); } list.append("<a href='?plugin=" + res[a][0] + "&pluginpg=" + res[a][1] + "'>" + res[a][2] + "</a></div>"); } return list.toString(); } public boolean isAdmin(String id) { return id.equals("admin"); } public boolean isAllowed(SQL sql, String id, String plugin, String pluginpg) { if (isAdmin(id)) return true; String res[][] = sql.select("SELECT plugin,pg FROM webpluginusers WHERE (userid=" + sql.quote(id) + " OR userid='*') AND plugin=" + sql.quote(plugin) + " AND pg=" + sql.quote(pluginpg)); return (res.length > 0); } public void redir(WebResponse response, String plugin, String pluginpg) { try { response.sendRedirect("/admin?plugin=" + plugin + "&pg=" + pluginpg); } catch(Exception e) { } } public String link(String plugin, String pluginpg, String params, String txt) { return "<a href='/admin?plugin=" + plugin + "&pluginpg=" + pluginpg + "&" + params + "'>" + txt + "</a>"; } public String form(String plugin, String pluginpg) { //TODO : use method=post return "<form action='/admin' method='get'><input type=hidden name=plugin value='" + plugin + "'><input type=hidden name=pluginpg value='" + pluginpg + "'>"; } public String formUpload(String plugin, String pluginpg, String args) { return "<form action='/admin?plugin=" + plugin + "&pluginpg=" + pluginpg + "&" + args +"' enctype='multipart/form-data' method='post'>"; } public String convertString(String instr) { //convert WebString to normal strings (expand %## codes, '+'->' ') String outstr = ""; char ca[] = instr.toCharArray(); int h1, h2; char ch; for(int a=0;a<ca.length;a++) { switch (ca[a]) { case '%': if (a+2>=ca.length) return outstr; if ((ca[a+1] >= '0') && (ca[a+1] <= '9')) h1 = ca[a+1] - '0'; else if ((ca[a+1] >= 'a') && (ca[a+1] <= 'f')) h1 = ca[a+1] - ('a' - 10); else if ((ca[a+1] >= 'A') && (ca[a+1] <= 'F')) h1 = ca[a+1] - ('A' - 10); else h1 = 0; if ((ca[a+2] >= '0') && (ca[a+2] <= '9')) h2 = ca[a+2] - '0'; else if ((ca[a+2] >= 'a') && (ca[a+2] <= 'f')) h2 = ca[a+2] - ('a' - 10); else if ((ca[a+2] >= 'A') && (ca[a+2] <= 'F')) h2 = ca[a+2] - ('A' - 10); else h2 = 0; ch = (char)(h1 * 0x10 + h2); if (ch == '\"') ch = '\''; outstr += ch; a+=2; break; case '+': outstr += " "; break; default: outstr += ca[a]; break; } } return outstr; } public String select(String name, String value, String list[]) { StringBuffer buf = new StringBuffer(); buf.append("<select name=" + name + "><option></option>"); if (list != null) { for(int a=0;a<list.length;a++) { buf.append("<option" + (list[a].equalsIgnoreCase(value) ? " selected" : "") + ">" + list[a] + "</option>"); } } buf.append("</select>"); return buf.toString(); } public String numbersOnly(String in) { String out = ""; char ca[] = in.toCharArray(); for(int a=0;a<ca.length;a++) { if ((ca[a] >= '0') && (ca[a] <= '9')) out += ca[a]; } return out; } public String patternsOnly(String in) { //TODO : make sure 'in' is valid patterns (':' delimited) //0-9,X,Z,N,.,|,+,: in = in.toUpperCase(); StringBuffer out = new StringBuffer(); int sl = in.length(); char ch; for(int a=0;a<sl;a++) { ch = in.charAt(a); if ((ch >= '0') && (ch <= '9')) { out.append(ch); continue; } switch (in.charAt(a)) { default: continue; case 'X': case 'Z': case 'N': case '.': case '|': case '+': case ':': out.append(ch); } } return out.toString(); } public boolean isBuiltinSound(String filename) { if (filename.equalsIgnoreCase("vm-0")) return true; if (filename.equalsIgnoreCase("vm-1")) return true; if (filename.equalsIgnoreCase("vm-2")) return true; if (filename.equalsIgnoreCase("vm-3")) return true; if (filename.equalsIgnoreCase("vm-4")) return true; if (filename.equalsIgnoreCase("vm-5")) return true; if (filename.equalsIgnoreCase("vm-6")) return true; if (filename.equalsIgnoreCase("vm-7")) return true; if (filename.equalsIgnoreCase("vm-8")) return true; if (filename.equalsIgnoreCase("vm-9")) return true; if (filename.equalsIgnoreCase("vm-beep")) return true; if (filename.equalsIgnoreCase("vm-deleted")) return true; if (filename.equalsIgnoreCase("vm-end-msgs")) return true; if (filename.equalsIgnoreCase("vm-enter-password")) return true; if (filename.equalsIgnoreCase("vm-goodbye")) return true; if (filename.equalsIgnoreCase("vm-greeting")) return true; if (filename.equalsIgnoreCase("vm-incorrect")) return true; if (filename.equalsIgnoreCase("vm-main-menu")) return true; if (filename.equalsIgnoreCase("vm-msg-menu")) return true; if (filename.equalsIgnoreCase("vm-msg")) return true; if (filename.equalsIgnoreCase("vm-new")) return true; if (filename.equalsIgnoreCase("vm-next")) return true; if (filename.equalsIgnoreCase("vm-no-msgs")) return true; if (filename.equalsIgnoreCase("vm-old")) return true; if (filename.equalsIgnoreCase("vm-pause")) return true; if (filename.equalsIgnoreCase("vm-rec-greeting")) return true; if (filename.equalsIgnoreCase("vm-rec-menu")) return true; if (filename.equalsIgnoreCase("vm-too-short")) return true; if (filename.equalsIgnoreCase("vm-welcome")) return true; if (filename.equalsIgnoreCase("conf-admin-left")) return true; if (filename.equalsIgnoreCase("conf-no-admin")) return true; if (filename.equalsIgnoreCase("acd-wait-for-agent")) return true; return false; } }