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");
}
}