• Post Reply Bookmark Topic Watch Topic
  • New Topic

Java policy file related problems  RSS feed

 
Sai Krishna Padmanabhan
Greenhorn
Posts: 1
C++ Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I am trying to set a new Security Manager using the code as below.
protected static void setandwritepolicyfile(){

FileWriter fw = null;

String hostaddress = null;

try{
hostaddress = InetAddress.getLocalHost().toString();
}catch (UnknownHostException ex_NOKIA55){
System.err.println(LiveDB.grassHopper(ex_NOKIA55,
"Host Adress not found Loopback address used"));
}

String [] SecurityPolicyLines =
{ // after initial testing change it to grant username signed by <username>
"grant",
"{",
"permission java.io.FilePermission " + "\"" + LiveDB.serializedfilespath + "-" + "\"" + "," + "\"" + "read,write,execute,delete" + "\"" + ";".toString(),
"permission java.io.FilePermission " + "\"" + LiveDB.serializedfilespath + "policy" + LiveDB.FILESEPERATOR + "*" + "\"" + "," + "\"" + "read,write,execute,delete" + "\"" + ";".toString(),
"permission java.io.FilePermission " + "\"" + LiveDB.TMPDIR + "-" + "\"" + "," + "\"" + "read,write,delete" + "\"" + ";".toString(),
"permission java.io.FilePermission " + "\"" + LiveDB.USRHOMEDIR + "-" + "\"" + "," + "\"" + "read,write,execute,delete" + "\"" + ";".toString(),
"permission java.io.FilePermission " + "\"" + LiveDB.USRDIR + "-" + "\"" + "," + "\"" + "read,write,execute,delete" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "smtp.gmail.com" + ":465" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "smtp.gmail.com" + ":587" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "IMAP.gmail.com" + ":143" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "POP3.gmail.com" + ":110" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "SSL-POP.gmail.com" + ":995" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "IMAPS.gmail.com" + ":993" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "IMAP4.gmail.com" + ":585" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "*.gmail.com" + ":1024" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "*.gmail.com" + ":49152" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "localhost" + ":1024" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "localhost" + ":25" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "localhost" + ":465" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "localhost" + ":587" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "localhost" + ":80" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "localhost" + ":585" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "localhost" + ":993" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "localhost" + ":995" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + "localhost" + ":110" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + hostaddress + ":25" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + hostaddress + ":465" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + hostaddress + ":587" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + hostaddress + ":80" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + hostaddress + ":585" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + hostaddress + ":993" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + hostaddress + ":995" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + hostaddress + ":110" + "\"" + "," + "\"" + "connect,accept,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + hostaddress + ":1024" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
"permission java.net.SocketPermission " + "\"" + hostaddress + ":49152" + "\"" + "," + "\"" + "connect,accept,listen,resolve" + "\"" + ";".toString(),
// permission java.util.PropertyPermission "java.util.logging.config.class", "read";
// permission java.util.PropertyPermission "java.util.logging.config.file", "read";
"permission java.util.PropertyPermission " + "\"" + "java.*" + "\"" + "," + "\"" + "read" + "\"" + ";".toString(),
"permission java.util.PropertyPermission " + "\"" + "line.*" + "\"" + "," + "\"" + "read" + "\"" + ";".toString(),
"permission java.util.PropertyPermission " + "\"" + "user.*" + "\"" + "," + "\"" + "read" + "\"" + ";".toString(),
//"permission java.util.PropertyPermission " + "\"" + "usr.*" + "\"" + "," + "\"" + "read" + "\"" + ";".toString(),
"permission java.util.PropertyPermission " + "\"" + "os.*" + "\"" + "," + "\"" + "read" + "\"" + ";".toString(),
"permission java.util.PropertyPermission " + "\"" + "file.*" + "\"" + "," + "\"" + "read" + "\"" + ";".toString(),
"permission java.util.PropertyPermission " + "\"" + "path.*" + "\"" + "," + "\"" + "read,write" + "\"" + ";".toString(),
"permission java.lang.SecurityPermission " + "\"" + "getPolicy" + "\"" + ";".toString(),
"permission java.lang.SecurityPermission " + "\"" + "setPolicy" + "\"" + ";".toString(),
"permission javax.audio.AudioPermission " + "\"" + "play" + "\"" + ";".toString(),
"permission java.util.logging.LoggingPermission " + "\"" + "control" + "\"" + ";".toString(),
"permission java.io.SerializablePermission " + "\"" + "enableSubclassImplementation" + "\"" + ";".toString(),
// this maybe dangerous perm
//"permission java.io.SerializablePermission " + "\"" + "enableSubstitution" + "\"" + ";".toString(),
// very dangerous perm
//"permission java.lang.reflect.ReflectPermission" + "\"" + "suppressAccessChecks" + "\"" + ";".toString(),
"permission java.net.NetPermission " + "\"" + "setDefaultAuthenticator" + "\"" + ";".toString(),
"permission java.net.NetPermission " + "\"" + "specifyStreamHandler" + "\"" + ";".toString(),
"permission java.net.NetPermission " + "\"" + "requestPasswordAuthentication" + "\"" + ";".toString(),
"permission java.net.NetPermission " + "\"" + "setProxySelector" + "\"" + ";".toString(),
"permission java.net.NetPermission " + "\"" + "getProxySelector" + "\"" + ";".toString(),
"permission java.net.NetPermission " + "\"" + "setCookieHandler" + "\"" + ";".toString(),
"permission java.net.NetPermission " + "\"" + "getCookieHandler" + "\"" + ";".toString(),
"permission java.net.NetPermission " + "\"" + "setResponseCache" + "\"" + ";".toString(),
"permission java.net.NetPermission " + "\"" + "getResponseCache" + "\"" + ";".toString(),
"permission java.lang.RuntimePermission " + "\"" + "usePolicy" + "\"" + ";".toString(),
"permission java.lang.RuntimePermission " + "\"" + "accessDeclaredMembers" + "\"" + ";".toString(),
"permission java.lang.RuntimePermission " + "\"" + "getStackTrace" + "\"" + ";".toString(),
"permission java.lang.RuntimePermission " + "\"" + "queuePrintJob" + "\"" + ";".toString(),
"permission java.lang.RuntimePermission " + "\"" + "setIO" + "\"" + ";".toString(),
"permission java.lang.RuntimePermission " + "\"" + "setContextClassLoader" + "\"" + ";".toString(),
"permission java.lang.RuntimePermission " + "\"" + "enableContextClassLoaderOverride" + "\"" + ";".toString(),
"permission java.lang.SecurityPermission " + "\"" + "getPolicy" + "\"" + ";".toString(),
//"permission java.lang.SecurityPermission " + "\"" + "printIdentity" + "\"" + ";".toString(),
"permission java.awt.AWTPermission " + "\"" + "showWindowWithoutWarningBanner" + "\"" + ";".toString(),
"permission java.awt.AWTPermission " + "\"" + "listenToAllAWTEvents" + "\"" + ";".toString(),
"permission java.awt.AWTPermission " + "\"" + "setAppletStub" + "\"" + ";".toString(),
"permission java.awt.AWTPermission " + "\"" + "watchMousePointer" + "\"" + ";".toString(),
"permission java.awt.AWTPermission " + "\"" + "readDisplayPixels" + "\"" + ";".toString(),
"permission java.awt.AWTPermission " + "\"" + "accessEventQueue" + "\"" + ";".toString(),
"permission java.awt.AWTPermission " + "\"" + "replaceKeyboardFocusManager" + "\"" + ";".toString(),
// added this extra line
"permission javax.security.auth.AuthPermission " + "\"" + "setReadOnly" + "\"" + ";".toString(),
"permission javax.security.auth.AuthPermission " + "\"" + "doAs" + "\"" + ";".toString(),
"permission javax.security.auth.AuthPermission " + "\"" + "doAsPrivileged" + "\"" + ";".toString(),
"permission javax.security.auth.AuthPermission " + "\"" + "getSubject" + "\"" + ";".toString(),
"permission javax.security.auth.AuthPermission " + "\"" + "getLoginConfiguration" + "\"" + ";".toString(),
"permission javax.security.auth.AuthPermission " + "\"" + "setLoginConfiguration" + "\"" + ";".toString(),
"permission javax.security.auth.AuthPermission " + "\"" + "refreshLoginConfiguration" + "\"" + ";".toString(),
"permission javax.security.auth.AuthPermission " + "\"" + "refreshCredential" + "\"" + ";".toString(),
"permission javax.security.auth.AuthPermission " + "\"" + "modifyPublicCredentials" + "\"" + ";".toString(),
"permission javax.security.auth.AuthPermission " + "\"" + "modifyPrivateCredentials" + "\"" + ";".toString(),
"permission javax.security.auth.AuthPermission " + "\"" + "modifyPrincipals" + "\"" + ";".toString(),
"};"
};

if (new File(LiveDB.USRHOMEDIR + ".java.policy").exists())
{
System.err.println(LiveDB.grassHopper("Override/AddOn .java.policy file exists in " + LiveDB.USRHOMEDIR + "DELETE"));
JOptionPane.showMessageDialog(appframe, "Override/AddOn .java.policy file exists in " +
'\n' + LiveDB.USRHOMEDIR + '\n'
+ "DELETE after consulting SYSADM");
JOptionPane.showMessageDialog(appframe, "This application will mis-behave" + '\n'
+ " if this " + LiveDB.USRHOMEDIR + ".java.policy" + '\n'
+ " file is not deleted. Delete yourself");
}

if (new File(LiveDB.serializedfilespath + "policy" + LiveDB.FILESEPERATOR
+ "PhotoDBApp.policy").exists())
{
if (new File(LiveDB.serializedfilespath + "policy" + LiveDB.FILESEPERATOR
+ "PhotoDBApp.policy").canWrite())
System.err.println(LiveDB.grassHopper(LiveDB.serializedfilespath + "policy"
+ LiveDB.FILESEPERATOR + "PhotoDBApp.policy has write perms possibly changed"));
return;
}

if (new File (LiveDB.serializedfilespath + "policy").canWrite())
{
System.err.println(LiveDB.grassHopper("File Perms Tampered:"+ LiveDB.serializedfilespath + "policy"));
}
else
{
if (new File (LiveDB.serializedfilespath + "policy").setWritable(true, false) == false )
System.err.println(LiveDB.grassHopper("Cant Set Perms File:"+ LiveDB.serializedfilespath + "policy"));
}

try{
fw = new FileWriter(new File(LiveDB.serializedfilespath + "policy"
+ LiveDB.FILESEPERATOR + "PhotoDBApp.policy"));
}catch (IOException ex_NOKIA18){
System.err.println(LiveDB.grassHopper(ex_NOKIA18,
"file exists directory not file,dont exist but cant create or open"));
System.exit(1);
}

for (int line = 0;line < SecurityPolicyLines.length; line++)
{
try{
fw.write(SecurityPolicyLines[line]);
}catch (IOException ex_NOKIA61){
System.err.println(LiveDB.grassHopper(ex_NOKIA61, "FileWriter write String error"));
JOptionPane.showMessageDialog(appframe, "IO ERROR IN WRITING SECURITY POLICY FILE CONTACT SYSADM");
System.exit(1);
}

try{
fw.append('\n');
}catch (IOException ex_NOKIA61){
System.err.println(LiveDB.grassHopper(ex_NOKIA61, "FileWriter append char error"));
JOptionPane.showMessageDialog(appframe, "IO ERROR IN WRITING SECURITY POLICY FILE CONTACT SYSADM");
System.exit(1);
}
}

try{
fw.close();
}catch (IOException ex_NOKIA11){
System.err.println(LiveDB.grassHopper(ex_NOKIA11, "write/flush post close() on FileWriter "
+ LiveDB.serializedfilespath + "policy" + LiveDB.FILESEPERATOR + "PhotoDBApp.policy"));
System.exit(1);
}

if ( new File (LiveDB.serializedfilespath + "policy").setReadOnly() == false)
{
LiveDB.ALRTLVL = 3;
System.err.println(LiveDB.grassHopper("Unable to set perms File:" +
LiveDB.serializedfilespath + "policy"));
}

// This call is creating problems. The application hangs on setReadonly after this call
System.setProperty("java.security.policy", LiveDB.serializedfilespath + "policy" +
LiveDB.FILESEPERATOR + "PhotoDBApp.policy");
//
try{
System.setSecurityManager(new SecurityManager());
}catch (SecurityException ex_NOKIA14){
System.err.println(LiveDB.grassHopper(ex_NOKIA14, " security manager preset its checkPermission dont allow replace "));
JOptionPane.showMessageDialog(appframe, " security manager preset its checkPermission dont allow replace Inform SYSADM");
}
JOptionPane.showMessageDialog(appframe, "Application Java Security Policy File:" + "\n" + LiveDB.serializedfilespath
+ "\n" + "policy" + LiveDB.FILESEPERATOR + "PhotoDBApp.policy");
JOptionPane.showMessageDialog(appframe,"Request System Administrator of Local" + "\n"
+ " Corporate Intranet Installation to "
+ "\n" + "give it a approval nod");

// I GET THE ERROR LISTED BELOW AS LINE 596 HERE
if (new File(LiveDB.serializedfilespath
+ "policy" + LiveDB.FILESEPERATOR + "PhotoDBApp.policy").setReadable(true,false) == false)
{
System.out.println("error setReadOnly");
System.err.println(LiveDB.grassHopper(LiveDB.serializedfilespath + "policy" + LiveDB.FILESEPERATOR
+ "PhotoDBApp.policy cant setReadOnly.Set at O/S"));
}

LiveDB.ALRTLVL = 5;
System.err.println (LiveDB.grassHopper("Application Security Policy " + LiveDB.serializedfilespath
+ "policy" + LiveDB.FILESEPERATOR + "PhotoDBApp.policy" + " Installed"));

}

The above code writes out a ppolicy file that looks as under

grant
{
permission java.io.FilePermission "C:\LensView312\-","read,write,execute,delete";
permission java.io.FilePermission "C:\LensView312\policy\*","read,write,execute,delete";
permission java.io.FilePermission "C:\DOCUME~1\SAIKRI~1\LOCALS~1\Temp\-","read,write,delete";
permission java.io.FilePermission "C:\Documents and Settings\SAI KRISHNA\-","read,write,execute,delete";
permission java.io.FilePermission "D:\MyJavaProjects\ArtLeaves\-","read,write,execute,delete";
permission java.net.SocketPermission "smtp.gmail.com:465","connect,accept,resolve";
permission java.net.SocketPermission "smtp.gmail.com:587","connect,accept,resolve";
permission java.net.SocketPermission "IMAP.gmail.com:143","connect,accept,resolve";
permission java.net.SocketPermission "POP3.gmail.com:110","connect,accept,resolve";
permission java.net.SocketPermission "SSL-POP.gmail.com:995","connect,accept,resolve";
permission java.net.SocketPermission "IMAPS.gmail.com:993","connect,accept,resolve";
permission java.net.SocketPermission "IMAP4.gmail.com:585","connect,accept,resolve";
permission java.net.SocketPermission "*.gmail.com:1024","connect,accept,resolve";
permission java.net.SocketPermission "*.gmail.com:49152","connect,accept,listen,resolve";
permission java.net.SocketPermission "localhost:1024","connect,accept,listen,resolve";
permission java.net.SocketPermission "localhost:25","connect,accept,listen,resolve";
permission java.net.SocketPermission "localhost:465","connect,accept,listen,resolve";
permission java.net.SocketPermission "localhost:587","connect,accept,listen,resolve";
permission java.net.SocketPermission "localhost:80","connect,accept,listen,resolve";
permission java.net.SocketPermission "localhost:585","connect,accept,listen,resolve";
permission java.net.SocketPermission "localhost:993","connect,accept,listen,resolve";
permission java.net.SocketPermission "localhost:995","connect,accept,listen,resolve";
permission java.net.SocketPermission "localhost:110","connect,accept,listen,resolve";
permission java.net.SocketPermission "Zoa/192.168.1.2:25","connect,accept,resolve";
permission java.net.SocketPermission "Zoa/192.168.1.2:465","connect,accept,resolve";
permission java.net.SocketPermission "Zoa/192.168.1.2:587","connect,accept,resolve";
permission java.net.SocketPermission "Zoa/192.168.1.2:80","connect,accept,resolve";
permission java.net.SocketPermission "Zoa/192.168.1.2:585","connect,accept,resolve";
permission java.net.SocketPermission "Zoa/192.168.1.2:993","connect,accept,resolve";
permission java.net.SocketPermission "Zoa/192.168.1.2:995","connect,accept,resolve";
permission java.net.SocketPermission "Zoa/192.168.1.2:110","connect,accept,resolve";
permission java.net.SocketPermission "Zoa/192.168.1.2:1024","connect,accept,listen,resolve";
permission java.net.SocketPermission "Zoa/192.168.1.2:49152","connect,accept,listen,resolve";
permission java.util.PropertyPermission "java.*","read";
permission java.util.PropertyPermission "line.*","read";
permission java.util.PropertyPermission "user.*","read";
permission java.util.PropertyPermission "os.*","read";
permission java.util.PropertyPermission "file.*","read";
permission java.util.PropertyPermission "path.*","read,write";
permission java.lang.SecurityPermission "getPolicy";
permission java.lang.SecurityPermission "setPolicy";
permission javax.audio.AudioPermission "play";
permission java.util.logging.LoggingPermission "control";
permission java.io.SerializablePermission "enableSubclassImplementation";
permission java.net.NetPermission "setDefaultAuthenticator";
permission java.net.NetPermission "specifyStreamHandler";
permission java.net.NetPermission "requestPasswordAuthentication";
permission java.net.NetPermission "setProxySelector";
permission java.net.NetPermission "getProxySelector";
permission java.net.NetPermission "setCookieHandler";
permission java.net.NetPermission "getCookieHandler";
permission java.net.NetPermission "setResponseCache";
permission java.net.NetPermission "getResponseCache";
permission java.lang.RuntimePermission "usePolicy";
permission java.lang.RuntimePermission "accessDeclaredMembers";
permission java.lang.RuntimePermission "getStackTrace";
permission java.lang.RuntimePermission "queuePrintJob";
permission java.lang.RuntimePermission "setIO";
permission java.lang.RuntimePermission "setContextClassLoader";
permission java.lang.RuntimePermission "enableContextClassLoaderOverride";
permission java.lang.SecurityPermission "getPolicy";
permission java.awt.AWTPermission "showWindowWithoutWarningBanner";
permission java.awt.AWTPermission "listenToAllAWTEvents";
permission java.awt.AWTPermission "setAppletStub";
permission java.awt.AWTPermission "watchMousePointer";
permission java.awt.AWTPermission "readDisplayPixels";
permission java.awt.AWTPermission "accessEventQueue";
permission java.awt.AWTPermission "replaceKeyboardFocusManager";
permission javax.security.auth.AuthPermission "setReadOnly";
permission javax.security.auth.AuthPermission "doAs";
permission javax.security.auth.AuthPermission "doAsPrivileged";
permission javax.security.auth.AuthPermission "getSubject";
permission javax.security.auth.AuthPermission "getLoginConfiguration";
permission javax.security.auth.AuthPermission "setLoginConfiguration";
permission javax.security.auth.AuthPermission "refreshLoginConfiguration";
permission javax.security.auth.AuthPermission "refreshCredential";
permission javax.security.auth.AuthPermission "modifyPublicCredentials";
permission javax.security.auth.AuthPermission "modifyPrivateCredentials";
permission javax.security.auth.AuthPermission "modifyPrincipals";
};

Now When I run my application (which can run both as an application and an applet) I get the following error
Exception in thread "main" java.security.AccessControlException: access denied (java.io.FilePermission C:\LensView312\policy\PhotoDBApp.policy write)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkWrite(SecurityManager.java:962)
at java.io.File.setReadable(File.java:1386)
at MaintainData.InstallDB.setandwritepolicyfile(InstallDB.java:596)
at MaintainData.LensView.main(LensView.java:464)

I am developing a Photographic Sales Software Open Source and the entire source code is posted at
http://www.fotokrafts.net/fotokrafts_java.html

Can somebody help with that error. Am I missing some permissions in the policy file ?

Thanks a ton

Sai.


 
Richard Tookey
Bartender
Posts: 1166
17
Java Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What is your aim in setting this new policy file? If to widen the permissions then allowing an application to define a wider set of permissions would defeat the object of having them in the first place. In effect an application could just arrange to ignore ALL security restrictions. If the aim is to narrow the restrictions then why? You are in control of what the program tries to do anyway !
 
Rob Spoor
Sheriff
Posts: 21135
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch!

Could you please UseCodeTags next time? Also, please KeepItDown, also in subject lines.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!