package jfconfig; /** * Created : Mar 16, 2012 * * @author pquiring */ import java.io.*; import java.util.Arrays; import javax.swing.*; import javaforce.*; import javaforce.linux.*; public class ProxyPanel extends javax.swing.JPanel { /** * Creates new form ProxyPanel */ public ProxyPanel() { initComponents(); loadRules(); updateRules(); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jToolBar1 = new javax.swing.JToolBar(); back = new javax.swing.JButton(); addRule = new javax.swing.JButton(); editRule = new javax.swing.JButton(); delRule = new javax.swing.JButton(); save = new javax.swing.JButton(); apply = new javax.swing.JButton(); restart = new javax.swing.JButton(); jScrollPane1 = new javax.swing.JScrollPane(); rules = new javax.swing.JList(); forwardedFor = new javax.swing.JCheckBox(); jLabel1 = new javax.swing.JLabel(); port = new javax.swing.JTextField(); jLabel2 = new javax.swing.JLabel(); jToolBar1.setFloatable(false); jToolBar1.setRollover(true); back.setText("<Back"); back.setFocusable(false); back.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); back.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); back.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { backActionPerformed(evt); } }); jToolBar1.add(back); addRule.setText("Add Rule"); addRule.setFocusable(false); addRule.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); addRule.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); addRule.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { addRuleActionPerformed(evt); } }); jToolBar1.add(addRule); editRule.setText("Edit Rule"); editRule.setFocusable(false); editRule.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); editRule.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); editRule.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { editRuleActionPerformed(evt); } }); jToolBar1.add(editRule); delRule.setText("Del Rule"); delRule.setFocusable(false); delRule.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); delRule.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); delRule.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { delRuleActionPerformed(evt); } }); jToolBar1.add(delRule); save.setText("Save"); save.setFocusable(false); save.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); save.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); save.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { saveActionPerformed(evt); } }); jToolBar1.add(save); apply.setText("Apply"); apply.setFocusable(false); apply.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); apply.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); apply.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { applyActionPerformed(evt); } }); jToolBar1.add(apply); restart.setText("Restart Server"); restart.setFocusable(false); restart.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); restart.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); restart.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { restartActionPerformed(evt); } }); jToolBar1.add(restart); rules.setModel(rulesModel); jScrollPane1.setViewportView(rules); forwardedFor.setSelected(true); forwardedFor.setText("Enable \"Forwarded-For\""); jLabel1.setText("Port"); port.setText("3128"); jLabel2.setText("Client Rules:"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jScrollPane1) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createSequentialGroup() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(port)) .addComponent(forwardedFor) .addComponent(jLabel2)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent(port, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(forwardedFor) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 504, Short.MAX_VALUE)) ); }// </editor-fold>//GEN-END:initComponents private void backActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backActionPerformed ConfigApp.This.setPanel(new ServersPanel()); }//GEN-LAST:event_backActionPerformed private void addRuleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addRuleActionPerformed addRule(); }//GEN-LAST:event_addRuleActionPerformed private void editRuleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editRuleActionPerformed int idx = rules.getSelectedIndex(); if (idx == -1) return; editRule(idx); }//GEN-LAST:event_editRuleActionPerformed private void delRuleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_delRuleActionPerformed int idx = rules.getSelectedIndex(); if (idx == -1) return; delRule(idx); }//GEN-LAST:event_delRuleActionPerformed private void saveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveActionPerformed saveRules(); }//GEN-LAST:event_saveActionPerformed private void applyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_applyActionPerformed apply(); }//GEN-LAST:event_applyActionPerformed private void restartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_restartActionPerformed restart(); }//GEN-LAST:event_restartActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton addRule; private javax.swing.JButton apply; private javax.swing.JButton back; private javax.swing.JButton delRule; private javax.swing.JButton editRule; private javax.swing.JCheckBox forwardedFor; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JToolBar jToolBar1; private javax.swing.JTextField port; private javax.swing.JButton restart; private javax.swing.JList rules; private javax.swing.JButton save; // End of variables declaration//GEN-END:variables /* Support Options: forwarded_for on|off http_port 3128 acl <src_name> src <ip/mask> acl <url_name> url_regex <url> http_access allow [<url_name>] <src_name> */ private DefaultListModel rulesModel = new DefaultListModel(); public static class Rule { public Rule() {}; public boolean enabled; public String ip; public String urls; //comma seperated ("all" = no limit) } public static class Config { public Rule rule[]; public boolean forwardedFor; } private Config config; private String configFolder = "/etc/jconfig.d/"; private String configFile = "proxy.xml"; private void loadRules() { config = new Config(); config.rule = new Rule[0]; try { XML xml = new XML(); FileInputStream fis = new FileInputStream(configFolder + configFile); xml.read(fis); xml.writeClass(config); } catch (FileNotFoundException e1) { defaultConfig(); } catch (Exception e2) { JFLog.log(e2); defaultConfig(); } forwardedFor.setSelected(config.forwardedFor); } private void defaultConfig() { config = new Config(); config.forwardedFor = true; config.rule = new Rule[0]; } private void saveRules() { config.forwardedFor = forwardedFor.isSelected(); try { XML xml = new XML(); File tmpFile = File.createTempFile("proxy", ".xml"); FileOutputStream fos = new FileOutputStream(tmpFile); xml.readClass("proxy", config); xml.write(fos); fos.close(); Linux.mkdir(configFolder); if (!Linux.copyFile(tmpFile.getAbsolutePath(), configFolder + configFile)) { tmpFile.delete(); throw new Exception("file io error"); } tmpFile.delete(); } catch (Exception e) { JFLog.log(e); } } private String getRuleString(Rule rule) { return rule.ip + ":" + rule.urls; } private void updateRules() { rulesModel.clear(); for(int a=0;a<config.rule.length;a++) { rulesModel.addElement(getRuleString(config.rule[a])); } forwardedFor.setSelected(config.forwardedFor); } private void up(int idx) { if (idx == 0) return; Rule tmp = config.rule[idx-1]; config.rule[idx-1] = config.rule[idx]; config.rule[idx] = tmp; updateRules(); rules.setSelectedIndex(idx-1); } private void down(int idx) { if (idx == config.rule.length-1) return; Rule tmp = config.rule[idx+1]; config.rule[idx+1] = config.rule[idx]; config.rule[idx] = tmp; updateRules(); rules.setSelectedIndex(idx+1); } private void addRule() { ProxyRuleDialog dialog = new ProxyRuleDialog(ConfigApp.This, true, null); dialog.setVisible(true); if (!dialog.accepted) return; Rule newRule = new Rule(); newRule.enabled = dialog.getEnabled(); newRule.ip = dialog.getIP(); newRule.urls = dialog.getURLs().replaceAll("\n", ","); config.rule = Arrays.copyOf(config.rule, config.rule.length + 1); config.rule[config.rule.length-1] = newRule; updateRules(); } private void editRule(int idx) { Rule rule = config.rule[idx]; ProxyRuleDialog dialog = new ProxyRuleDialog(ConfigApp.This, true, rule); dialog.setVisible(true); if (!dialog.accepted) return; rule.enabled = dialog.getEnabled(); rule.ip = dialog.getIP(); rule.urls = dialog.getURLs().replaceAll("\n", ","); updateRules(); } private void delRule(int idx) { Rule rule = config.rule[idx]; if (!JF.showConfirm("Confirm", "Are you sure you want to delete '" + rule.ip + "'?")) return; int len = config.rule.length; Rule newList[] = new Rule[len-1]; System.arraycopy(config.rule, 0, newList, 0, idx); System.arraycopy(config.rule, idx+1, newList, idx, len - idx - 1); config.rule = newList; updateRules(); } //acl <src_name> src <ip/mask> //acl <url_name> url_regex <url> //http_access allow [<url_name>] <src_name> private void applyRules(OutputStream os) throws Exception { os.write("#JCONFIG-START:DO NOT EDIT THESE LINES-AUTO GENERATED FROM JCONFIG\n".getBytes()); for(int a=0;a<config.rule.length;a++) { Rule rule = config.rule[a]; if (!rule.enabled) continue; os.write(("acl rule_ip_" + a + " src " + rule.ip + "\n").getBytes()); if (rule.urls.equals("all")) { os.write(("http_access allow rule_ip_" + a + "\n").getBytes()); } else { String lns[] = rule.urls.split(","); for(int b=0;b<lns.length;b++) { String regex = lns[b].replaceAll("[.]", "[.]"); //looks strange but replaces . with [.] os.write(("acl rule_url_" + a + "_" + b + " url_regex " + regex + "\n").getBytes()); os.write(("http_access allow rule_url_" + a + "_" + b + " rule_ip_" + a + "\n").getBytes()); } } } os.write("#JCONFIG-STOP:DO NOT EDIT THESE LINES-AUTO GENERATED FROM JCONFIG\n".getBytes()); } private void apply() { try { //copy /etc/squid3/squid.conf to tmpFile changing settings on the fly File tmpFile = File.createTempFile("proxy", ".xml"); FileOutputStream fos = new FileOutputStream(tmpFile); FileInputStream fis = new FileInputStream("/etc/squid3/squid.conf"); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); String ln; boolean inRules = false, insertRules = false, rulesApplied = false; while ((ln = br.readLine()) != null) { if (inRules) { if (ln.startsWith("#JCONFIG-STOP")) inRules = false; continue; } else { if (ln.startsWith("#JCONFIG-START")) {inRules = true; continue;} else if ((!rulesApplied) && (ln.indexOf("INSERT YOUR OWN RULE") != -1)) { insertRules = true; } else if ((ln.startsWith("forwarded_for ")) || (ln.startsWith("# forwarded_for "))) { if (config.forwardedFor) { fos.write("forwarded_for on\n".getBytes()); } else { fos.write("forwarded_for off\n".getBytes()); } continue; } } fos.write(ln.getBytes()); fos.write("\n".getBytes()); if (insertRules) { applyRules(fos); insertRules = false; rulesApplied = true; } } fos.close(); fis.close(); if (inRules) { tmpFile.delete(); JF.showError("Error", "Squid config is corrupt, can not apply settings"); return; } //copy tmpFile back to /etc/squid3/squid.conf if (!Linux.copyFile(tmpFile.getAbsolutePath(), "/etc/squid3/squid.conf")) throw new Exception("file copy error"); tmpFile.delete(); JF.showMessage("Notice", "Settings have been applied, please restart server."); } catch (Exception e) { JFLog.log(e); JF.showError("Error", "Failed to apply settings."); } } private void restart() { if (Linux.restartService("squid3")) JF.showMessage("Notice", "Squid Service Restarted"); else JF.showError("Error", "Failed to Restart Squid Service"); } }