----
Here is the source code to the PostBack plugin.  Someone may find this useful in developing their own plugins.  Same rules on how to make the package structure. ([Third Party])
----
Start.java
----
%%prettify 
{{{

package PostBack;

import java.util.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
import crushftp.handlers.Common;
import crushftp.server.ServerStatus;

public class Start implements Serializable
{
	Properties settings = new Properties();
	String version = "4.1";
	GUI g = null;

	public Properties getDefaults()
	{
		Properties p = new Properties();
		p.put("enabled","false");
		p.put("debug","false");
		p.put("send_alerts","false");
		p.put("url","");
		p.put("retry_count","0");
		p.put("max_full_speed","10");
		p.put("delay_interval","3000");
		p.put("username","");
		p.put("password","");
		p.put("post_data","");
		p.put("recent","false");
		p.put("version",version);
		return p;
	}

	public void setSettings(Properties p) throws Exception
	{
		settings = p;
		if (g != null) g.setSettings(settings);
	}

	public Properties getSettings()
	{
		if (g != null) settings = g.getSettings();
		settings.put("version",version);
		return settings;
	}

	public javax.swing.JPanel getPrefsPanel()
	{
		if (g == null) g = new GUI();
		g.setParent(this);
		g.setSettings(settings);
		return g;
	}

	public String replace_vars(String the_line, Properties user_info, Properties p,crushftp.server.ServerSession thisSession)
	{
		try{the_line = Common.replace_str(the_line, "%user_name%", URLEncoder.encode(user_info.getProperty("user_name",""), "UTF-8"));}catch(Exception e){}
		try{the_line = Common.replace_str(the_line, "%user_ip%", URLEncoder.encode(user_info.getProperty("user_ip",""), "UTF-8"));}catch(Exception e){}
		String path = "";
		try{path = new URL(p.getProperty("url","")).getPath();}catch(Exception e){}
		if (Common.machine_is_windows()) try{path = new File(path).getCanonicalPath();}catch(Exception e){}
		try{the_line = Common.replace_str(the_line, "%the_real_path%", URLEncoder.encode(path, "UTF-8"));}catch(Exception e){}
		try{the_line = Common.replace_str(the_line, "%the_file_path%", URLEncoder.encode(p.getProperty("the_file_path",""), "UTF-8"));}catch(Exception e){}
		try{the_line = Common.replace_str(the_line, "%the_file_name%", URLEncoder.encode(p.getProperty("the_file_name",""), "UTF-8"));}catch(Exception e){}
		the_line = Common.replace_str(the_line, "%the_file_size%", p.getProperty("the_file_size",""));
		the_line = Common.replace_str(the_line, "%the_file_speed%", p.getProperty("the_file_speed",""));
		the_line = Common.replace_str(the_line, "%the_file_start%", p.getProperty("the_file_start",""));
		the_line = Common.replace_str(the_line, "%the_file_end%", p.getProperty("the_file_end",""));
		the_line = Common.replace_str(the_line, "%the_file_md5%", p.getProperty("the_file_md5",""));
		the_line = Common.replace_str(the_line, "%the_command%", p.getProperty("the_command",""));
		try{the_line = Common.replace_str(the_line, "%the_file_error%", URLEncoder.encode(p.getProperty("the_file_error",""), "UTF-8"));}catch(Exception e){}
		try{the_line = thisSession.server_status_frame.change_vars_to_values(the_line,thisSession);}catch(Exception e){}
		return the_line;
	}

	public Object run(Properties info)
	{
		if (!settings.getProperty("enabled").equalsIgnoreCase("true")) return null;

		String error = "";
		try
		{
			if (info.getProperty("action","").equals("event")) //we only get called with an event if this plugin was targeted for an event
			{
				Vector items = (Vector)((Vector)info.get("items")).clone();
				Properties user = (Properties)info.get("user");
				Properties user_info = (Properties)info.get("user_info");
				msg("item list size:"  +items.size());
				msg("items:"  +items);
				int processed = 0;
				int x = 0;
				while(x<items.size())
				{
					if (settings.getProperty("recent","").equals("true")) x = items.size()-1;
					Properties p = (Properties)items.elementAt(x);
					msg(p.toString());
					String url = replace_vars(settings.getProperty("url"),user_info,p,(crushftp.server.ServerSession)info.get("ServerSession"));
					String post_data = replace_vars(settings.getProperty("post_data",""),user_info,p,(crushftp.server.ServerSession)info.get("ServerSession"));
					msg("url before:"+settings.getProperty("url"));
					msg("post_data before:"+settings.getProperty("post_data"));
					msg("url after:"+url);
					msg("post_data after:"+post_data);
					error = new java.util.Date()+"\r\n\r\nPostBack plugin failed:\r\n";
					error += "post_data:"+post_data;
					for (int xx=0; xx<Integer.parseInt(get("retry_count"))+1; xx++)
					{
						try
						{
							Common.debug(0,"PostBack: url="+url);
							HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection();
							connection.setDoOutput(true);
							connection.setDoInput(true);
							if (get("username").trim().length() > 0)
							{
								String authString = get("username")+":"+get("password");
								String auth = "Basic " + new sun.misc.BASE64Encoder().encode(authString.getBytes());
								connection.setRequestProperty("Authorization", auth);
							}
							byte dataBytes[] = post_data.getBytes();
							connection.setRequestMethod("POST");
							connection.setRequestProperty("Content-Length", dataBytes.length+"");
							OutputStream os = connection.getOutputStream();
							os.write(dataBytes);
							os.flush();

							BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
							String decodedString = "";
							while ((decodedString = in.readLine()) != null)
							{
								msg(decodedString);
							}
							in.close();
							break;
						}
						catch(Exception e)
						{
							Common.debug(0,"PostBack: Error="+e.getMessage());
							msg(e);
							error += "\r\nError:"+e.toString();
							if (xx == Integer.parseInt(get("retry_count")))
							{
								if (get("send_alerts").equals("true"))
								{
									crushftp.server.ServerSession thisSession = (crushftp.server.ServerSession)info.get("ServerSession");
									ServerStatus.thisObj.runAlerts("pluginMessage_"+error,thisSession);
								}
							}
							else
							{
								Thread.sleep(10000);
							}

						}
						if (settings.getProperty("debug").equals("true"))
						{
							String s = "PostBack\r\nThis url was just called:\r\n"+url+"\r\n\r\n"+post_data;
							msg(s);
						}
					}
					if (processed++ > Integer.parseInt(get("max_full_speed"))) Thread.sleep(Integer.parseInt(get("delay_interval")));
					x++;
				}
			}
		}
		catch(Exception e)
		{
			msg(e);
			error += "\r\nError:"+e.toString();
			if (get("send_alerts").equals("true"))
			{
				crushftp.server.ServerSession thisSession = (crushftp.server.ServerSession)info.get("ServerSession");
				ServerStatus.thisObj.runAlerts("pluginMessage_"+error,thisSession);
			}
		}
		return null;
	}

	public void testSettings()
	{
		String error = "OK";
		JOptionPane.showMessageDialog(null, error, "Alert",JOptionPane.ERROR_MESSAGE);
	}

	public String get(String key)
	{
		return settings.getProperty(key);
	}

	public void msg(String s)
	{
		if (settings.getProperty("debug").equals("true")) Common.debug(0,"PostBack:"+s);
	}

	public void msg(Exception e)
	{
		if (settings.getProperty("debug").equals("true")) Common.debug(0,e);
	}


}
}}}
/%
----
GUI.java
----
%%prettify 
{{{
package PostBack;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.lang.reflect.*;

public class GUI extends JPanel
{
	private JLabel jLabel1 = new JLabel();
	private JTextField url_field = new JTextField();

	public GUI()
	{
		try
		{
			jbInit();
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
	}

	Object parent = null;
	private JPanel jPanel1 = new JPanel();
	private JCheckBox enabled_cb = new JCheckBox();
	private JCheckBox debug_cb = new JCheckBox();
	private JCheckBox recent_cb = new JCheckBox();
	private JLabel jLabel2 = new JLabel();
	private JLabel jLabel3 = new JLabel();
	private JLabel jLabel4 = new JLabel();
	private JLabel jLabel5 = new JLabel();
	private JTextField post_data_field = new JTextField();
	private JLabel jLabel7 = new JLabel();
	private JLabel jLabel11 = new JLabel();
	private JTextField username_field = new JTextField();
	private JLabel jLabel6 = new JLabel();
	private JLabel jLabel8 = new JLabel();
	private JPasswordField password_field = new JPasswordField();
	private JCheckBox send_alerts_cb = new JCheckBox();
	private JLabel jLabel9 = new JLabel();
	private JTextField retry_count_field = new JTextField();
	private JTextField max_full_speed = new JTextField();
	private JLabel jLabel10 = new JLabel();
	private JTextField delay_interval = new JTextField();
	private JLabel jLabel12 = new JLabel();

	public void setParent(Object parent)
	{
		this.parent = parent;
	}

	void jbInit() throws Exception
	{
		jLabel1.setFont(new java.awt.Font("Arial", 0, 12));
		jLabel1.setText("URL:");
		jLabel1.setBounds(new Rectangle(9, 44, 72, 29));
		this.setLayout(null);
		url_field.setBounds(new Rectangle(84, 46, 457, 22));
		jPanel1.setBorder(BorderFactory.createEtchedBorder());
		jPanel1.setBounds(new Rectangle(3, 38, 583, 334));
		jPanel1.setLayout(null);
		enabled_cb.setFont(new java.awt.Font("Arial", 0, 12));
		enabled_cb.setText("Enabled");
		enabled_cb.setBounds(new Rectangle(6, 6, 100, 22));
		debug_cb.setBounds(new Rectangle(122, 6, 100, 22));
		debug_cb.setFont(new java.awt.Font("Arial", 0, 12));
		debug_cb.setText("Debug");
		recent_cb.setFont(new java.awt.Font("Arial", 0, 12));
		recent_cb.setToolTipText("");
		recent_cb.setText("Only use most recent item.");
		recent_cb.setBounds(new Rectangle(86, 234, 213, 22));
		jLabel2.setFont(new java.awt.Font("Arial", 0, 12));
		jLabel2.setText("If this is for an event where the event happens immediately, and");
		jLabel2.setBounds(new Rectangle(108, 257, 472, 16));
		jLabel3.setFont(new java.awt.Font("Arial", 0, 12));
		jLabel3.setText("not just on logout, this will only process the most recent item.");
		jLabel3.setBounds(new Rectangle(108, 280, 472, 16));
		jLabel4.setFont(new java.awt.Font("Arial", 0, 12));
		jLabel4.setText("Otherwise, it will go through each item executing the command on " + "each.");
		jLabel4.setBounds(new Rectangle(108, 303, 472, 16));
		jLabel5.setFont(new java.awt.Font("Arial", 0, 9));
		jLabel5.setHorizontalAlignment(SwingConstants.CENTER);
		jLabel5.setHorizontalTextPosition(SwingConstants.CENTER);
		jLabel5.setText("<html><body><center>%user_name%, %the_real_pathl%, %the_file_path%, " + "%the_file_name%, <br>%the_file_size%, %the_file_speed%, %the_file_start%, " + "%the_file_end%, %the_file_error%</center></body></html>");
		jLabel5.setBounds(new Rectangle(5, 9, 573, 29));
		post_data_field.setBounds(new Rectangle(84, 183, 457, 22));
		jLabel7.setBounds(new Rectangle(9, 180, 72, 29));
		jLabel7.setText("Post Data:");
		jLabel7.setFont(new java.awt.Font("Arial", 0, 12));
		jLabel11.setFont(new java.awt.Font("Arial", 0, 12));
		jLabel11.setText("Enable debug mode to see how the url was called.");
		jLabel11.setBounds(new Rectangle(84, 214, 494, 16));
		username_field.setBounds(new Rectangle(252, 79, 95, 22));
		jLabel6.setBounds(new Rectangle(9, 76, 245, 29));
		jLabel6.setText("Basic Authentication Username (optional):");
		jLabel6.setFont(new java.awt.Font("Arial", 0, 12));
		jLabel8.setBounds(new Rectangle(352, 76, 121, 29));
		jLabel8.setText("Password (optional):");
		jLabel8.setFont(new java.awt.Font("Arial", 0, 12));
		password_field.setBounds(new Rectangle(472, 79, 95, 22));
		send_alerts_cb.setBounds(new Rectangle(9, 107, 221, 22));
		send_alerts_cb.setText("Alert notifications on failures.");
		send_alerts_cb.setFont(new java.awt.Font("Arial", 0, 12));
		send_alerts_cb.setOpaque(false);
		jLabel9.setFont(new java.awt.Font("Arial", 0, 12));
		jLabel9.setText("Retry x times on failure:");
		jLabel9.setBounds(new Rectangle(212, 104, 139, 29));
		retry_count_field.setBounds(new Rectangle(343, 107, 47, 22));
		max_full_speed.setBounds(new Rectangle(283, 143, 47, 22));
		jLabel10.setBounds(new Rectangle(12, 140, 278, 29));
		jLabel10.setText("Maximum files per event that post without delay:");
		jLabel10.setFont(new java.awt.Font("Arial", 0, 12));
		delay_interval.setBounds(new Rectangle(491, 143, 47, 22));
		jLabel12.setBounds(new Rectangle(335, 140, 174, 29));
		jLabel12.setText("Delay between event posts:");
		jLabel12.setFont(new java.awt.Font("Arial", 0, 12));
		this.add(jPanel1, null);
		jPanel1.add(jLabel5, null);
		this.add(enabled_cb, null);
		this.add(debug_cb, null);
		jPanel1.add(jLabel1, null);
		jPanel1.add(url_field, null);
		jPanel1.add(jLabel6, null);
		jPanel1.add(username_field, null);
		jPanel1.add(jLabel8, null);
		jPanel1.add(password_field, null);
		jPanel1.add(send_alerts_cb, null);
		jPanel1.add(jLabel9, null);
		jPanel1.add(retry_count_field, null);
		jPanel1.add(jLabel7, null);
		jPanel1.add(jLabel4, null);
		jPanel1.add(jLabel3, null);
		jPanel1.add(jLabel2, null);
		jPanel1.add(recent_cb, null);
		jPanel1.add(jLabel11, null);
		jPanel1.add(post_data_field, null);
		jPanel1.add(jLabel10, null);
		jPanel1.add(max_full_speed, null);
		jPanel1.add(jLabel12, null);
		jPanel1.add(delay_interval, null);
	}

	public Properties getSettings()
	{
		Properties p = new Properties();
		p.put("enabled", enabled_cb.isSelected() + "");
		p.put("debug", debug_cb.isSelected() + "");
		p.put("send_alerts", send_alerts_cb.isSelected() + "");
		p.put("url", url_field.getText());
		p.put("retry_count", retry_count_field.getText());
		p.put("max_full_speed", max_full_speed.getText());
		p.put("delay_interval", delay_interval.getText());
		p.put("username", username_field.getText());
		p.put("password", new String(password_field.getPassword()));
		p.put("post_data", post_data_field.getText());
		p.put("recent", recent_cb.isSelected() + "");
		return p;
	}

	public void setSettings(Properties p)
	{
		enabled_cb.setSelected(p.getProperty("enabled").equalsIgnoreCase("true"));
		debug_cb.setSelected(p.getProperty("debug").equalsIgnoreCase("true"));
		send_alerts_cb.setSelected(p.getProperty("send_alerts", "false").equalsIgnoreCase("true"));
		url_field.setText(p.getProperty("url"));
		retry_count_field.setText(p.getProperty("retry_count"));
		max_full_speed.setText(p.getProperty("max_full_speed"));
		delay_interval.setText(p.getProperty("delay_interval"));
		username_field.setText(p.getProperty("username"));
		password_field.setText(p.getProperty("password"));

		post_data_field.setText(p.getProperty("post_data"));
		recent_cb.setSelected(p.getProperty("recent").equalsIgnoreCase("true"));
	}

	void test_btn_actionPerformed(ActionEvent e)
	{
		Properties p = getSettings();
		try
		{
			Method setSettings = parent.getClass().getMethod("setSettings", new Class[] { new Properties().getClass() });
			setSettings.invoke(parent, new Object[] { p });
			Method testSettings = parent.getClass().getMethod("testSettings", null);
			testSettings.invoke(parent, null);
		}
		catch (Exception ee)
		{
		}
	}
}
}}}
/%