425 error ftp over SSL in Java - java

Using the Apache commons library, I am attempting to put a file or to list directory contents on the remote server that is connected using FTP over SSL.
public void outboundProcessFile(String inputFilePath, String outputFilePath) throws Exception {
File inFile = new java.io.File(inputFilePath);
if (args == null){
System.exit(-1) ;
}
String args[] = this.args;
boolean storeFile = false, binaryTransfer = false, error = false, listFiles = false, listNames = false, hidden = false;
boolean mlst = false, mlsd = false;
boolean lenient = true;
boolean feat = true;;
long keepAliveTimeout = 300000;
int controlKeepAliveReplyTimeout = 300000;
int minParams = 5;
String doCommand = "PROT P";//null
String server = null, password = null, username = null, remote = null,local = null;
int port = 990;//990
int base = 0;
for (base = 0; base < args.length; base++) {
if (args[base].equals("-s")) {
storeFile = true;
} else if (args[base].equals("-b")) {
binaryTransfer = true;
} else if (args[base].equals("-c")) {
doCommand = args[++base];
minParams = 3;
} else if (args[base].equals("-d")) {
mlsd = true;
minParams = 3;
} else if (args[base].equals("-h")) {
hidden = true;
} else if (args[base].equals("-k")) {
keepAliveTimeout = Long.parseLong(args[++base]);
} else if (args[base].equals("-l")) {
listFiles = true;
minParams = 3;
} else if (args[base].equals("-L")) {
lenient = true;
} else if (args[base].equals("-n")) {
listNames = true;
minParams = 3;
} else if (args[base].equals("-t")) {
mlst = true;
minParams = 3;
} else if (args[base].equals("-w")) {
controlKeepAliveReplyTimeout = Integer.parseInt(args[++base]);
} else if (args[base].equals("-sh")) {
server = args[++base];
String parts[] = server.split(":");
if (parts.length == 2){
server=parts[0];
port=Integer.parseInt(parts[1]);
}
} else if (args[base].equals("-u")) {
username = args[++base];
} else if (args[base].equals("-pw")) {
password = args[++base];
} else if (args[base].equals("-rf")) {
remote = null;
if (args.length - base > 0) {
remote = args[++base];
}
} else if (args[base].equals("-lf")) {
local = null;
if (args.length - base > 0) {
local = args[++base];
}
} else {
break;
}
}
FTPClient ftp;
FTPSClient ftps = new FTPSClient(true);
ftp = ftps;
ftps.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
ftp.setCopyStreamListener(createListener());
if (keepAliveTimeout >= 0) {
ftp.setControlKeepAliveTimeout(keepAliveTimeout);
}
if (controlKeepAliveReplyTimeout >= 0) {
ftp.setControlKeepAliveReplyTimeout(controlKeepAliveReplyTimeout);
}
ftp.setListHiddenFiles(hidden);
// suppress login details
ftp.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
try {
int reply;
if (port > 0) {
ftp.connect(server, port);
} else {
ftp.connect(server);
}
System.out.println("Connected to " + server + " on "+ftp.getRemotePort());
// After connection attempt, you should check the reply code to verify
// success.
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
System.err.println("FTP server refused connection.");
System.exit(1);
}
}
catch (IOException e) {
if (ftp.isConnected()) {
try {
ftp.disconnect();
}
catch (IOException f)
{
// do nothing
}
}
System.err.println("Could not connect to server.");
e.printStackTrace();
System.exit(1);
}
__main:
try
{
String userid = null;//
if (!ftp.login(username, password)) {
ftp.logout();
error = true;
break __main;
}
System.out.println("Remote system is " + ftp.getSystemType());
if (feat) {
// boolean feature check
if (remote != null) { // See if the command is present
if (ftp.hasFeature(remote)) {
System.out.println("Has feature: "+remote);
} else {
if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
// System.out.println("FEAT "+remote+" was not detected");
} else {
System.out.println("Command failed: "+ftp.getReplyString());
}
}
// Strings feature check
String []features = ftp.featureValues(remote);
if (features != null) {
for(String f : features) {
System.out.println("FEAT "+remote+"="+f+".");
}
} else {
if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
// System.out.println("FEAT "+remote+" is not present");
} else {
System.out.println("Command failed: "+ftp.getReplyString());
}
}
} else {
if (ftp.features()) {
// Command listener has already printed the output
} else {
System.out.println("Failed: "+ftp.getReplyString());
}
}
}
ftp.doCommandAsStrings("PBSZ", "0");
ftp.doCommandAsStrings("PROT", "P");
if (binaryTransfer)
ftp.setFileType(FTP.ASCII_FILE_TYPE);//.BINARY_FILE_TYPE);
// Use passive mode as default because most of us are
// behind firewalls these days.
ftp.enterLocalPassiveMode();
ftp.doCommand("MLSD", "");
if (storeFile) {
InputStream input;
input = new FileInputStream(local);
ftp.changeWorkingDirectory(remote);
ftp.storeFile(local.substring(local.lastIndexOf("/")+1), input);
input.close();
} else if (listFiles) {
if (lenient) {
FTPClientConfig config = new FTPClientConfig();
config.setLenientFutureDates(true);
ftp.configure(config );
}
for (FTPFile f : ftp.listFiles(remote)) {
System.out.println(f.getRawListing());
System.out.println(f.toFormattedString());
}
} else if (mlsd) {
for (FTPFile f : ftp.mlistDir(remote)) {
System.out.println(f.getRawListing());
System.out.println(f.toFormattedString());
}
} else if (mlst) {
FTPFile f = ftp.mlistFile(remote);
if (f != null){
System.out.println(f.toFormattedString());
}
} else if (listNames) {
for (String s : ftp.listNames(remote)) {
System.out.println(s);
}
} else {
OutputStream output;
output = new FileOutputStream(local);
ftp.changeWorkingDirectory(remote);
ftp.retrieveFile(local.substring(local.lastIndexOf("/")), output);
output.close();
}
ftp.noop(); // check that control connection is working OK
ftp.logout();
} catch (FTPConnectionClosedException e) {
error = true;
System.err.println("Server closed connection.");
e.printStackTrace();
} catch (IOException e) {
error = true;
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException f) {
// do nothing
}
}
}
System.exit(error? -1:0);
}
I run this and get console output for listing...
220 Serv-U FTP Server v6.4 for WinSock ready...
Connected to ftps.server.com on 990
USER *******
331 User name okay, need password.
PASS *******
230 User logged in, proceed.
SYST
215 UNIX Type: L8
Remote system is UNIX Type: L8
FEAT
211-Extension supported
AUTH TLS
SSCN
PBSZ
PROT
CCC
CLNT
MDTM
MDTM YYYYMMDDHHMMSS[+-TZ];filename
SIZE
SITE PSWD;EXEC;SET;INDEX;ZONE;CHMOD;MSG
REST STREAM
XCRC filename;start;end
MODE Z
MLST Type*;Size*;Create;Modify*;Win32.ea*;
211 End
PBSZ 0
200 PBSZ command OK. Protection buffer size set to 0.
PROT P
200 PROT command OK. Using private data connection.
TYPE A
200 Type set to A.
MLSD
150 Opening BINARY mode data connection for MLSD.
PASV
227 Entering Passive Mode (204,124,192,88,195,82)
LIST Directory/toIC/
425 Try later, data connection in use.
NOOP
150 Opening BINARY mode data connection for MLSD.
QUIT
200 Command okay.
If I do not MLSD and attempt to upload a file, I will see a 0 byte file with the file name placed on the server (via FileZilla) and I will get a 421 error. Ideas?

I had to remove the MLSD command. I can now list, retrieve and stor.

Related

Java mail is there a better way to read emails?

I have some code to read people's inbox, with a filter on send TO or FROM. The time it takes to make it process the messages is far too long.
The search term filters my total emails down to 6 emails from a specific sender, yet to process the emails it takes 4 seconds to create my email objects. I'm wondering if there is a better / faster way to do this. since I want to use this for more than just 6 emails. I'm using imaps settings with user and password to authenticate.
public static List<Email> readBox(String host, String user, String pass, String protocol, String port,String downloadDir,String checksubject,String checkatt,List<String> checkfromemail,List<String> checktoemail,String mailFolder) throws Exception {
int iport = 0;
StopWatch stopwatch = new StopWatch();
stopwatch.start();
try{
iport = Integer.parseInt(port.trim());
}catch(Exception e){}
List<Email> emails = new ArrayList<Email>();
Properties props = new Properties();
Session session = Session.getDefaultInstance(props);
URLName urln = new URLName(protocol, host, iport, null, user, pass);
Store store = session.getStore(urln);
store.connect(host, user, pass);
Folder folder = store.getFolder(mailFolder);
folder.open(Folder.READ_WRITE);
try {
OrTerm orTerms = null;
SearchTerm terms = null;
if(checkfromemail.size()>0) {
SearchTerm [] search = new SearchTerm[checkfromemail.size()];
for(int j = 0; j < checkfromemail.size(); j++) {
search[j] = new FromStringTerm(checkfromemail.get(j).trim());
}
orTerms = new OrTerm(search);
}
if(checktoemail.size() > 0) {
SearchTerm [] search = new SearchTerm[checktoemail.size()];
for(int j = 0; j < checktoemail.size(); j++) {
search[j] = new RecipientStringTerm(Message.RecipientType.TO, checktoemail.get(0).trim());
}
orTerms = new OrTerm(search);
}
if(orTerms != null) {
emails = readInboxMailBox(folder.search(orTerms),downloadDir,checksubject,checkatt,checkfromemail,checktoemail,false,-1);
}else {
emails = readInboxMailBox(folder.getMessages(),downloadDir,checksubject,checkatt,checkfromemail,checktoemail,false,-1);
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}finally {
folder.close(false);
store.close();
}
stopwatch.stop();
System.out.println("readed emails in " + stopwatch.getTotalTimeMillis() + " miliseconds ");
return emails;
}
private static List<Email> readInboxMailBox(Message[] messages,String downloadDir,String checksubject,String checkatt,List<String> checkfromemail,List<String> checkmailto,boolean delete,int numberOfMessages) {
List<Email> emails = new ArrayList<Email>();
StopWatch stopwatch = new StopWatch();
stopwatch.start();
try {
// Get directory listing
for (int i = 0; i < messages.length; i++) {
// get last message
if(numberOfMessages > 0) {
if(i < ( messages.length - numberOfMessages)) {
continue;
}
}
Email email = new Email();
// from
email.from = messages[i].getFrom()[0].toString();
// cc list
Address[] toArray = null;
try {
toArray = messages[i].getRecipients(Message.RecipientType.TO);
} catch (Exception e) { toArray = null; }
if (toArray != null) {
for (Address to : toArray) {
email.to.add(to.toString());
}
}
// cc list
Address[] ccArray = null;
try {
ccArray = messages[i].getRecipients(Message.RecipientType.CC);
} catch (Exception e) { ccArray = null; }
if (ccArray != null) {
for (Address c : ccArray) {
email.cc.add(c.toString());
}
}
// subject
email.subject = messages[i].getSubject();
if(!checksubject.trim().equals("")) {
if(!email.subject.toLowerCase().contains(checksubject.toLowerCase().trim())) {
continue;
}
}
// received date
if (messages[i].getReceivedDate() != null) {
email.received = messages[i].getReceivedDate();
} else {
email.received = new Date();
}
// body and attachments
email.body = "";
Object content = messages[i].getContent();
if (content instanceof java.lang.String) {
email.body = (String) content;
} else if (content instanceof Multipart) {
Multipart mp = (Multipart) content;
for (int j = 0; j < mp.getCount(); j++) {
Part part = mp.getBodyPart(j);
String disposition = part.getDisposition();
if (disposition == null) {
MimeBodyPart mbp = (MimeBodyPart) part;
if (mbp.isMimeType("text/plain") || mbp.isMimeType("text/html")) {
// Plain
email.body += (String) mbp.getContent();
}
else if (mbp.isMimeType("multipart/*")) {
MimeMultipart mimeMultipart = (MimeMultipart) mbp.getContent();
try {
email.body += getTextFromMimeMultipart(mimeMultipart);
}catch(Exception e) {
e.printStackTrace();
}
}
}
// else if ((disposition != null) && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) {
//
// if(decodeName(part.getFileName()).trim().endsWith(".vcf")){
// continue;
// }
// if(!checkatt.trim().equals("")) {
// String checkfile = decodeName(part.getFileName()).trim();
// if(!isFileMatchTargetFilePattern(checkfile,checkatt.trim())){
// continue;
// }
// }
// EmailAttachment attachment = new EmailAttachment();
//
// attachment.name = saveName(decodeName(part.getFileName()));
// File savedir = new File(downloadDir);
// savedir.mkdirs();
// File savefile = new File(downloadDir,attachment.name);
// String path = STR.Replace(savefile.getAbsolutePath(),attachment.name,"");
// attachment.path = path;
// attachment.size = saveFile(savefile, part);
// email.attachments.add(attachment);
//
// }
} // end of multipart for loop
} // end messages for loop
if(!checkatt.trim().equals("")) {
if(email.attachments.size()<=0) {
continue;
}
}
emails.add(email);
// Finally delete the message from the server.
if(delete) {
messages[i].setFlag(Flags.Flag.DELETED, true);
}else {
//messages[i].setFlag(Flags.Flag.SEEN, true);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
}
stopwatch.stop();
System.out.println("processed emails in " + stopwatch.getTotalTimeMillis() + " miliseconds ");
return emails;
}
private static String getTextFromMimeMultipart(MimeMultipart mimeMultipart) throws MessagingException, IOException{
String result = "";
int count = mimeMultipart.getCount();
for (int i = 0; i < count; i++) {
BodyPart bodyPart = mimeMultipart.getBodyPart(i);
if (bodyPart.isMimeType("text/plain")) {
result = result + "\n" + bodyPart.getContent();
break; // without break same text appears twice in my tests
} else if (bodyPart.isMimeType("text/html")) {
String html = (String) bodyPart.getContent();
result = result + "\n" + org.jsoup.Jsoup.parse(html).text();
} else if (bodyPart.getContent() instanceof MimeMultipart){
result = result + getTextFromMimeMultipart((MimeMultipart)bodyPart.getContent());
}
}
return result;
}

Read and Write to USB Device on Raspberry Pi 3 using Java

I'm using Raspbian on a Raspberry Pi 3. I'm learning how to code in Java (SE runtime version 1.8.0_65), and I need to communicate raw data with a USB connected Bill Acceptor. According to the manufacturer's documentation, the USB unit mimics a serial-type interface. When I plug the device in, it appears in /dev/serial/by-id. I wrote C code 20+ years ago using modems on SCO Unix setups. If memory serves, I basically treated the modems /dev/ttyxx as a file for reading and writing. I wrote a C++ program 10+ years ago on Windows XP using a similar Bill Acceptor unit (same manufacturer and model) connected to a serial port instead of USB. The documentation shows both USB and serial units use the same data strings for input and output, so I know the SendString data should be correct for triggering a valid response. However, I'm not getting a reply from the unit, so I'm guessing I'm not connecting properly to it.
Here is the code...
public static void main(String[] args) {
try
{
System.out.println("*****************************");
System.out.println("***** Starting Program *****");
System.out.println("*****************************");
String strUsbDeviceDir = "/dev/serial/by-id";
File myUsbDeviceDir = new File(strUsbDeviceDir);
if(myUsbDeviceDir.exists())
{
String[] myUsbDevices = myUsbDeviceDir.list();
for(int i=0; i<myUsbDevices.length; i++)
{
if(myUsbDevices[i].contains("EBDS_over_USB"))
{
System.out.println("Connecting to " + myUsbDevices[i]);
funcBillAcceptor(strUsbDeviceDir + "/" + myUsbDevices[i]);
}
else
{
System.out.println("Not using " + myUsbDevices[i]);
}
}
}
}
catch (Exception ex)
{
System.err.println(ex.toString());
}
}
public static void funcBillAcceptor(String strBillAcceptor)
{
boolean bOddCount = false;
byte[] SendString = new byte[8];
byte[] RecvString = new byte[10];
byte CheckDigit;
int iSendStringCount, iRecvStringCount, iRecvEmptyCount;
try
{
File fBillAcceptor = new File(strBillAcceptor);
if(!fBillAcceptor.canRead())
{
System.out.println("No Read Permission for " + strBillAcceptor);
return;
}
if(!fBillAcceptor.canWrite())
{
System.out.println("No Write Permission for " + strBillAcceptor);
return;
}
RandomAccessFile rafBillAcceptor = new RandomAccessFile(strBillAcceptor, "rwd");
if(rafBillAcceptor != null)
{
System.out.println("Successfully opened " + strBillAcceptor);
}
while(fBillAcceptor.exists())
{
SendString[0] = (byte) 0x02; //STX
SendString[1] = (byte) 0x08;
if(bOddCount)
{
SendString[2] = (byte) 0x10;
bOddCount = false;
}
else
{
SendString[2] = (byte) 0x11;
bOddCount = true;
}
SendString[3] = (byte) 0x1F;
SendString[4] = (byte) 0x0C;
SendString[5] = (byte) 0x00;
SendString[6] = (byte) 0x03; //ETX
//CheckDigit skips STX (byte 0) with byte 1 as seed/initial value
//To calculate the check digit, start with next byte (2)
CheckDigit = SendString[1];
iSendStringCount = 2;
while(SendString[iSendStringCount] != 0x03)
{
CheckDigit = (byte) (SendString[iSendStringCount]^CheckDigit); //XOR current CheckDigit value with next byte
iSendStringCount++;
}
iSendStringCount++; //advance one more so we don't overwrite ETX
SendString[iSendStringCount] = (byte) CheckDigit;
try
{
rafBillAcceptor.write(SendString);
System.out.println("Sent: " + DatatypeConverter.printHexBinary(SendString));
}
catch (Exception ex)
{
System.err.println("Write exception: " + ex.toString());
}
System.out.println("Reading...");
iRecvStringCount = iRecvEmptyCount = 0;
try
{
do
{
iRecvStringCount = rafBillAcceptor.read(RecvString);
System.out.println("Read " + iRecvStringCount + " bytes.");
if(iRecvStringCount < 0)
{
iRecvEmptyCount++;
Thread.sleep(5);
}
} while (iRecvStringCount < 0 && iRecvEmptyCount < 100);
if(iRecvStringCount > 0)
{
System.out.println("Received: " + DatatypeConverter.printHexBinary(RecvString));
}
}
catch (Exception ex)
{
System.err.println("Read exception: " + ex.toString());
}
}
}
catch (Exception ex)
{
System.err.println(ex.toString());
}
}
Here is the output I'm getting...
*****************************
***** Starting Program *****
*****************************
Connecting to usb-Silicon_Labs_Series_2000_Bill_Acceptor__EBDS_over_USB__46580120748-if00-port0
Successfully opened /dev/serial/by-id/usb-Silicon_Labs_Series_2000_Bill_Acceptor__EBDS_over_USB__46580120748-if00-port0
Sent: 0208111F0C00030A
Reading...
Am I missing something obvious, or just going about this all wrong? Thanks for any suggestions!
I was able to successfully communicate with the Bill Acceptor from a Raspberry Pi 3 (running Raspbian) using the RXTXComm library. When communicating with the device from an old Windows XP computer using a 9-pin serial/RS232 harness, I had to use 9600/7/E/1. If I don't use those values for setSerialPortParams (in my sample code), I'm not able to correctly send/receive data. So, you need to know what the device is expecting in order to use this approach with other "serial" hardware connected via USB. Below is code with the basic functionality. I started with one of the sample programs that come with the RXTXComm library and built out from there. Since this is a sample program, I haven't yet added logic to verify the checksum digit for data coming from the device.
You may notice at the bottom of the code that I'm able to determine the /dev/ttyUSBx using the canonical name of the device that I pull from the /dev/serial/by-id directory/folder. It finds the correct device name regardless of which USB port the unit is plugged in to or what order the USB devices get initialized by the system. I have a card dispenser that is also a USB serial device, so I was able to test and confirm this functionality.
public TwoWaySerialComm()
{
super();
}
static boolean bReadyToSend = false;
void connect ( String portName ) throws Exception
{
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if ( portIdentifier.isCurrentlyOwned() )
{
System.out.println("Error: " + portName + " is currently in use.");
}
else
{
CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
if ( commPort instanceof SerialPort )
{
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_7, SerialPort.STOPBITS_1, SerialPort.PARITY_EVEN);
InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();
// Thread handling logic
// https://www.javaspecialists.eu/archive/Issue056.html
Thread readThread = new Thread(new SerialReader(in));
readThread.start();
Thread writeThread = new Thread(new SerialWriter(out));
writeThread.start();
// Running threads for 10 seconds then stopping to ensure threads are shutting down
long threadCurrTime = System.currentTimeMillis();
long threadStartTime = System.currentTimeMillis();
while( (threadCurrTime - threadStartTime) < 10000)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException ex)
{
Logger.getLogger(TwoWaySerialComm.class.getName()).log(Level.SEVERE, null, ex);
}
threadCurrTime = System.currentTimeMillis();
}
if(writeThread.isAlive())
{
//System.out.println("Sending interrupt to SerialWriter thread...");
writeThread.interrupt();
writeThread.join();
//System.out.println("SerialWriter thread is shut down.");
}
//else
//{
// System.out.println("SerialWriter thread is already shut down.");
//}
if(readThread.isAlive())
{
//System.out.println("Sending interrupt to SerialReader thread...");
readThread.interrupt();
readThread.join();
//System.out.println("SerialReader thread is shut down.");
}
//else
//{
// System.out.println("SerialReader thread is already shut down.");
//}
commPort.close();
}
else
{
System.out.println("Error: " + portName + " is not recognized as a valid serial device.");
}
}
}
/* SerialReader thread logic */
public static class SerialReader implements Runnable
{
InputStream in;
boolean bShuttingDown = false;
public SerialReader ( InputStream in )
{
this.in = in;
}
public void run ()
{
byte[] RecvString = new byte[12];
String strResponse;
int len = -1;
try
{
while (!bShuttingDown)
{
len = this.in.read(RecvString);
if( len > -1 )
{
strResponse = "";
if(RecvString[0] == 0x02 && RecvString[9] == 0x03)
{
if(RecvString[3] == 0x00 && RecvString[4] == 0x00 && RecvString[5] == 0x00 && RecvString[6] == 0x00)
{
strResponse = "Device not ready.";
}
else
{
//-- RecvString[3]------------------
if(RecvString[3] == 0x01)
strResponse = " - Idling";
else
if(RecvString[3] == 0x02)
strResponse = " - Accepting";
else
if(RecvString[3] == 0x04)
{
strResponse = " - Escrowed";
if(RecvString[5] == 0x08)
strResponse += " $1";
else
if(RecvString[5] == 0x10)
strResponse += " $2";
else
if(RecvString[5] == 0x18)
strResponse += " $5";
else
if(RecvString[5] == 0x20)
strResponse += " $10";
else
if(RecvString[5] == 0x28)
strResponse += " $20";
else
strResponse += " unrecognized bill inserted";
}
else
if(RecvString[3] == 0x08)
strResponse = " - Stacking";
else
if(RecvString[3] == 0x10)
strResponse = " - Stacked";
else
if(RecvString[3] == 0x11)
strResponse = " - Returning";
else
if(RecvString[3] == 0x12)
strResponse = " - Returned";
//-- RecvString[4]------------------
if(RecvString[4] == 0x01)
strResponse += " - Cheated";
else
if(RecvString[4] == 0x02)
strResponse += " - Rejected";
else
if(RecvString[4] == 0x04)
strResponse += " - Jammed";
else
if(RecvString[4] == 0x08)
strResponse += " - Bill Stacker Full";
else
if(RecvString[4] == 0x10)
strResponse += " - Removable Cassette Installed";
else
if(RecvString[4] == 0x11)
strResponse += " - Reserved";
else
if(RecvString[4] == 0x12)
strResponse += " - Calibration mode";
//-- RecvString[5]------------------
if(RecvString[5] == 0x01)
strResponse += " - Power Up Reset";
else
if(RecvString[5] == 0x02)
strResponse += " - Invalid Command";
else
if(RecvString[5] == 0x04)
strResponse += " - Non-recoverable fault";
}
if(!strResponse.contains("Idling"))
System.out.println("Recv: " + DatatypeConverter.printHexBinary(RecvString) + strResponse);
}
else
{
System.out.println("Recv (invalid): " + DatatypeConverter.printHexBinary(RecvString));
}
try
{
Thread.sleep(100); // need this delay before we send next polling message, otherwise the data doesn't come in correctly
bReadyToSend = true;
}
catch (InterruptedException ex)
{
Thread.currentThread().interrupt();
//System.out.println("Shut down SerialReader thread.");
bShuttingDown = true;
break;
}
}
}
}
catch ( IOException ex )
{
System.out.println("Recv exception: " + ex.toString());
}
}
}
/* SerialWriter thread logic */
public static class SerialWriter implements Runnable
{
OutputStream out;
long lastSendTime = System.currentTimeMillis() - 1001;
long currSendTime;
byte[] SendString = new byte[8];
byte CheckDigit;
int iSendStringCount;
boolean bOddCount = true;
boolean bShuttingDown = false;
public SerialWriter ( OutputStream out )
{
this.out = out;
}
public void run ()
{
while(!bShuttingDown)
{
currSendTime = System.currentTimeMillis();
if(currSendTime - lastSendTime > 1000) // if it's been more than a second, send query string
bReadyToSend = true;
if(bReadyToSend)
{
SendString[0] = (byte) 0x02; //STX
SendString[1] = (byte) 0x08;
if(bOddCount)
{
SendString[2] = (byte) 0x10;
bOddCount = false;
}
else
{
SendString[2] = (byte) 0x11;
bOddCount = true;
}
SendString[3] = (byte) 0x7F;
SendString[4] = (byte) 0x1C;
SendString[5] = (byte) 0x00;
SendString[6] = (byte) 0x03; //ETX
//CheckDigit skips STX (byte 0) with byte 1 as seed/initial value
//To calculate the check digit, start with next byte (2)
CheckDigit = SendString[1];
iSendStringCount = 2;
while(SendString[iSendStringCount] != 0x03)
{
CheckDigit = (byte) (SendString[iSendStringCount]^CheckDigit); //XOR current CheckDigit value with next byte
iSendStringCount++;
}
iSendStringCount++; //advance one more so we don't overwrite ETX
SendString[iSendStringCount] = (byte) CheckDigit;
try
{
lastSendTime = System.currentTimeMillis();
this.out.write(SendString);
//System.out.println("Sent: " + DatatypeConverter.printHexBinary(SendString));
}
catch ( IOException ex )
{
System.out.println("Send exception: " + ex.toString());
}
try
{
Thread.sleep(1); // this is hear simply to catch an external interrupt
}
catch (InterruptedException ex)
{
Thread.currentThread().interrupt();
//System.out.println("Shut down SerialWriter thread.");
bShuttingDown = true;
break;
}
bReadyToSend = false;
}
}
}
}
public static void main ( String[] args )
{
try
{
System.out.println("*****************************");
System.out.println("***** Starting Program *****");
System.out.println("*****************************");
String strUsbDeviceDir = "/dev/serial/by-id";
File myUsbDeviceDir = new File(strUsbDeviceDir);
if(myUsbDeviceDir.exists())
{
String[] myUsbDevices = myUsbDeviceDir.list();
for(int i=0; i<myUsbDevices.length; i++)
{
if(myUsbDevices[i].contains("EBDS_over_USB"))
{
File tempFile = new File(strUsbDeviceDir + "/" + myUsbDevices[i]);
String usbCanonicalName = tempFile.getCanonicalFile().toString(); //gives me /dev/ttyUSBx where 'x' is the USB device number
System.out.println("Connecting to " + usbCanonicalName + " (" + myUsbDevices[i] + ")");
(new TwoWaySerialComm()).connect(usbCanonicalName);
}
else
{
System.out.println("Not using " + myUsbDevices[i]);
}
}
}
}
catch ( Exception ex )
{
System.out.println("Connect exception: " + ex.toString());
}
System.out.println("*****************************");
System.out.println("***** Program Finished ******");
System.out.println("*****************************");
}
Output when I put a $1 bill in (I'm developing/compiling from NetBeans IDE 8.2 on Windows 10 Pro and running using remote debugging on the RPi3. I'm guessing that's the source of the RXTX Version mismatch warning):
*****************************
***** Starting Program *****
*****************************
Connecting to /dev/ttyUSB0 (usb-Silicon_Labs_Series_2000_Bill_Acceptor__EBDS_over_USB__46580120748-if00-port0)
Stable Library
=========================================
Native lib Version = RXTX-2.2pre2
Java lib Version = RXTX-2.1-7
WARNING: RXTX Version mismatch
Jar version = RXTX-2.1-7
native lib Version = RXTX-2.2pre2
Recv (invalid): 020000000000000000000000
Recv (invalid): 0B2001100800503603540000
Recv: 020B20041008005036035100 - Escrowed $1 - Removable Cassette Installed
*****************************
***** Program Finished ******
*****************************
I hope this description and sample code can help someone else.

Error: A JNI error has occurred (javax.mail.jar)

I'm trying to read gmail messages using showmsg.java in the javamail sample package, and I keep getting this error when I run it. The program compiles fine though.
Here's the error message:
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: javax/mail/internet/ParseException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: javax.mail.internet.ParseException
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
Here's the code:
import java.util.*;
import java.io.*;
import javax.mail.*;
import javax.mail.event.*;
import javax.mail.internet.*;
/*
* Demo app that exercises the Message interfaces.
* Show information about and contents of messages.
*
* #author John Mani
* #author Bill Shannon
*/
public class msgshow {
static String protocol;
static String host = null;
static String user = null;
static String password = null;
static String mbox = null;
static String url = null;
static int port = -1;
static boolean verbose = false;
static boolean debug = false;
static boolean showStructure = false;
static boolean showMessage = false;
static boolean showAlert = false;
static boolean saveAttachments = false;
static int attnum = 1;
public static void main(String argv[]) {
int optind;
InputStream msgStream = System.in;
for (optind = 0; optind < argv.length; optind++) {
if (argv[optind].equals("-T")) {
protocol = argv[++optind];
} else if (argv[optind].equals("-H")) {
host = argv[++optind];
} else if (argv[optind].equals("-U")) {
user = argv[++optind];
} else if (argv[optind].equals("-P")) {
password = argv[++optind];
} else if (argv[optind].equals("-v")) {
verbose = true;
} else if (argv[optind].equals("-D")) {
debug = true;
} else if (argv[optind].equals("-f")) {
mbox = argv[++optind];
} else if (argv[optind].equals("-L")) {
url = argv[++optind];
} else if (argv[optind].equals("-p")) {
port = Integer.parseInt(argv[++optind]);
} else if (argv[optind].equals("-s")) {
showStructure = true;
} else if (argv[optind].equals("-S")) {
saveAttachments = true;
} else if (argv[optind].equals("-m")) {
showMessage = true;
} else if (argv[optind].equals("-a")) {
showAlert = true;
} else if (argv[optind].equals("--")) {
optind++;
break;
} else if (argv[optind].startsWith("-")) {
System.out.println(
"Usage: msgshow [-L url] [-T protocol] [-H host] [-p port] [-U user]");
System.out.println(
"\t[-P password] [-f mailbox] [msgnum ...] [-v] [-D] [-s] [-S] [-a]");
System.out.println(
"or msgshow -m [-v] [-D] [-s] [-S] [-f msg-file]");
System.exit(1);
} else {
break;
}
}
try {
// Get a Properties object
Properties props = System.getProperties();
// Get a Session object
Session session = Session.getInstance(props, null);
session.setDebug(debug);
if (showMessage) {
MimeMessage msg;
if (mbox != null)
msg = new MimeMessage(session,
new BufferedInputStream(new FileInputStream(mbox)));
else
msg = new MimeMessage(session, msgStream);
dumpPart(msg);
System.exit(0);
}
// Get a Store object
Store store = null;
if (url != null) {
URLName urln = new URLName(url);
store = session.getStore(urln);
if (showAlert) {
store.addStoreListener(new StoreListener() {
public void notification(StoreEvent e) {
String s;
if (e.getMessageType() == StoreEvent.ALERT)
s = "ALERT: ";
else
s = "NOTICE: ";
System.out.println(s + e.getMessage());
}
});
}
store.connect();
} else {
if (protocol != null)
store = session.getStore(protocol);
else
store = session.getStore();
// Connect
if (host != null || user != null || password != null)
store.connect(host, port, user, password);
else
store.connect();
}
// Open the Folder
Folder folder = store.getDefaultFolder();
if (folder == null) {
System.out.println("No default folder");
System.exit(1);
}
if (mbox == null)
mbox = "INBOX";
folder = folder.getFolder(mbox);
if (folder == null) {
System.out.println("Invalid folder");
System.exit(1);
}
// try to open read/write and if that fails try read-only
try {
folder.open(Folder.READ_WRITE);
} catch (MessagingException ex) {
folder.open(Folder.READ_ONLY);
}
int totalMessages = folder.getMessageCount();
if (totalMessages == 0) {
System.out.println("Empty folder");
folder.close(false);
store.close();
System.exit(1);
}
if (verbose) {
int newMessages = folder.getNewMessageCount();
System.out.println("Total messages = " + totalMessages);
System.out.println("New messages = " + newMessages);
System.out.println("-------------------------------");
}
if (optind >= argv.length) {
// Attributes & Flags for all messages ..
Message[] msgs = folder.getMessages();
// Use a suitable FetchProfile
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
fp.add(FetchProfile.Item.FLAGS);
fp.add("X-Mailer");
folder.fetch(msgs, fp);
for (int i = 0; i < msgs.length; i++) {
System.out.println("--------------------------");
System.out.println("MESSAGE #" + (i + 1) + ":");
dumpEnvelope(msgs[i]);
// dumpPart(msgs[i]);
}
} else {
while (optind < argv.length) {
int msgnum = Integer.parseInt(argv[optind++]);
System.out.println("Getting message number: " + msgnum);
Message m = null;
try {
m = folder.getMessage(msgnum);
dumpPart(m);
} catch (IndexOutOfBoundsException iex) {
System.out.println("Message number out of range");
}
}
}
folder.close(false);
store.close();
} catch (Exception ex) {
System.out.println("Oops, got exception! " + ex.getMessage());
ex.printStackTrace();
System.exit(1);
}
System.exit(0);
}
public static void dumpPart(Part p) throws Exception {
if (p instanceof Message)
dumpEnvelope((Message)p);
/** Dump input stream ..
InputStream is = p.getInputStream();
// If "is" is not already buffered, wrap a BufferedInputStream
// around it.
if (!(is instanceof BufferedInputStream))
is = new BufferedInputStream(is);
int c;
while ((c = is.read()) != -1)
System.out.write(c);
**/
String ct = p.getContentType();
try {
pr("CONTENT-TYPE: " + (new ContentType(ct)).toString());
} catch (ParseException pex) {
pr("BAD CONTENT-TYPE: " + ct);
}
String filename = p.getFileName();
if (filename != null)
pr("FILENAME: " + filename);
/*
* Using isMimeType to determine the content type avoids
* fetching the actual content data until we need it.
*/
if (p.isMimeType("text/plain")) {
pr("This is plain text");
pr("---------------------------");
if (!showStructure && !saveAttachments)
System.out.println((String)p.getContent());
} else if (p.isMimeType("multipart/*")) {
pr("This is a Multipart");
pr("---------------------------");
Multipart mp = (Multipart)p.getContent();
level++;
int count = mp.getCount();
for (int i = 0; i < count; i++)
dumpPart(mp.getBodyPart(i));
level--;
} else if (p.isMimeType("message/rfc822")) {
pr("This is a Nested Message");
pr("---------------------------");
level++;
dumpPart((Part)p.getContent());
level--;
} else {
if (!showStructure && !saveAttachments) {
/*
* If we actually want to see the data, and it's not a
* MIME type we know, fetch it and check its Java type.
*/
Object o = p.getContent();
if (o instanceof String) {
pr("This is a string");
pr("---------------------------");
System.out.println((String)o);
} else if (o instanceof InputStream) {
pr("This is just an input stream");
pr("---------------------------");
InputStream is = (InputStream)o;
int c;
while ((c = is.read()) != -1)
System.out.write(c);
} else {
pr("This is an unknown type");
pr("---------------------------");
pr(o.toString());
}
} else {
// just a separator
pr("---------------------------");
}
}
/*
* If we're saving attachments, write out anything that
* looks like an attachment into an appropriately named
* file. Don't overwrite existing files to prevent
* mistakes.
*/
if (saveAttachments && level != 0 && p instanceof MimeBodyPart &&
!p.isMimeType("multipart/*")) {
String disp = p.getDisposition();
// many mailers don't include a Content-Disposition
if (disp == null || disp.equalsIgnoreCase(Part.ATTACHMENT)) {
if (filename == null)
filename = "Attachment" + attnum++;
pr("Saving attachment to file " + filename);
try {
File f = new File(filename);
if (f.exists())
// XXX - could try a series of names
throw new IOException("file exists");
((MimeBodyPart)p).saveFile(f);
} catch (IOException ex) {
pr("Failed to save attachment: " + ex);
}
pr("---------------------------");
}
}
}
public static void dumpEnvelope(Message m) throws Exception {
pr("This is the message envelope");
pr("---------------------------");
Address[] a;
// FROM
if ((a = m.getFrom()) != null) {
for (int j = 0; j < a.length; j++)
pr("FROM: " + a[j].toString());
}
// REPLY TO
if ((a = m.getReplyTo()) != null) {
for (int j = 0; j < a.length; j++)
pr("REPLY TO: " + a[j].toString());
}
// TO
if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
for (int j = 0; j < a.length; j++) {
pr("TO: " + a[j].toString());
InternetAddress ia = (InternetAddress)a[j];
if (ia.isGroup()) {
InternetAddress[] aa = ia.getGroup(false);
for (int k = 0; k < aa.length; k++)
pr(" GROUP: " + aa[k].toString());
}
}
}
// SUBJECT
pr("SUBJECT: " + m.getSubject());
// DATE
Date d = m.getSentDate();
pr("SendDate: " +
(d != null ? d.toString() : "UNKNOWN"));
// FLAGS
Flags flags = m.getFlags();
StringBuffer sb = new StringBuffer();
Flags.Flag[] sf = flags.getSystemFlags(); // get the system flags
boolean first = true;
for (int i = 0; i < sf.length; i++) {
String s;
Flags.Flag f = sf[i];
if (f == Flags.Flag.ANSWERED)
s = "\\Answered";
else if (f == Flags.Flag.DELETED)
s = "\\Deleted";
else if (f == Flags.Flag.DRAFT)
s = "\\Draft";
else if (f == Flags.Flag.FLAGGED)
s = "\\Flagged";
else if (f == Flags.Flag.RECENT)
s = "\\Recent";
else if (f == Flags.Flag.SEEN)
s = "\\Seen";
else
continue; // skip it
if (first)
first = false;
else
sb.append(' ');
sb.append(s);
}
String[] uf = flags.getUserFlags(); // get the user flag strings
for (int i = 0; i < uf.length; i++) {
if (first)
first = false;
else
sb.append(' ');
sb.append(uf[i]);
}
pr("FLAGS: " + sb.toString());
// X-MAILER
String[] hdrs = m.getHeader("X-Mailer");
if (hdrs != null)
pr("X-Mailer: " + hdrs[0]);
else
pr("X-Mailer NOT available");
}
static String indentStr = " ";
static int level = 0;
/**
* Print a, possibly indented, string.
*/
public static void pr(String s) {
if (showStructure)
System.out.print(indentStr.substring(0, level * 2));
System.out.println(s);
}
}
The command I'm using to run is java msgshow -D -T imaps -H imap.gmail.com -U [USER] -P [PASS] and the command I'm using to compile it is javac -cp ".:./:./lib:./lib/*" msgshow.java. The javax.mail.jar is contained in the lib folder
This is some alternate code that's much shorter and gets the same errors:
import java.util.*;
import java.io.*;
import javax.mail.*;
import smtp;
import imaps;
//import java.mail.*;
//import com.sun.mail.*;
public class AccessGmail {
public static void main (String[] args) {
Scanner scan = new Scanner(System.in);
try
{
Properties prop = new Properties();
prop.load(new FileInputStream(new File("smtp.properties")));
Session session = Session.getDefaultInstance(prop, null);
String pass = scan.next();
Store store = session.getStore("imaps");
store.connect("smtp.gmail.com","shane.l.gvoice#gmail.com",pass);
Folder inbox = store.getFolder("inbox");
inbox.open(Folder.READ_ONLY);
int messageCount = inbox.getMessageCount();
System.out.println("Message Count: "+messageCount);
}
catch (FileNotFoundException e){}
catch (IOException e){}
catch(NoSuchProviderException e){}
catch(MessagingException e){}
}
}
You're not setting the CLASSPATH when you're running the program so it's not finding the javax.mail.jar file:
java -cp ".:lib/javax.mail.jar" msgshow -D -T imaps -H imap.gmail.com -U [USER] -P [PASS]

java: check boolean in for loop

If work.length is 4 ,
I have to check the AResult in for loop
If 4 AResult all are true ,set result.setstatus("success");
or result.setstatus("fail");
What can I do ??
for(int i = 0;i < work.length;i++){
if(!work[i].contains("#")){
CommandLineInterface CLI = new CommandLineInterface();
String IP = null;
boolean AResult;
try {
AResult = CLI.Setting(work[i],"start"); //true or false
} catch (JSchException | InterruptedException e) {
e.printStackTrace();
}
}
}
//result.setstatus("success"); //all true
//result.setstatus("fail");
Add a counter. Increment it when your condition is true. Check the value of the counter after your loop. Something like
int counter = 0;
for(int i = 0;i < work.length;i++){
if(!work[i].contains("#")){
CommandLineInterface CLI = new CommandLineInterface();
String IP = null;
boolean AResult;
try {
AResult = CLI.Setting(work[i],"start");
if (AResult) {
counter++;
}
} catch (JSchException | InterruptedException e) {
e.printStackTrace();
}
}
}
if (work.length == 4 && counter == 4) {
result.setstatus("success");
} else {
result.setstatus("fail");
}
You could optimize the above (and reduce the code size) with something like
int counter = 0;
if (work.length == 4) { // <-- check the length first
for (int i = 0; i < work.length; i++) {
if (!work[i].contains("#")) {
CommandLineInterface CLI = new CommandLineInterface();
try {
if (CLI.Setting(work[i], "start")) {
counter++; // <-- increment the counter.
} else {
break; // <-- break on any fale.
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
result.setstatus(counter == 4 ? "success" : "fail"); // <-- setstatus
try this, you really don't need to iterate the loop till end when a false condition is encountered in between
//initially set success
result.setstatus("success");
for(int i = 0;i < work.length;i++){
if(!work[i].contains("#")){
CommandLineInterface CLI = new CommandLineInterface();
String IP = null;
try {
if(CLI.Setting(work[i],"start"))
{
result.setstatus("fail");
//no need to iterate further
break;
}
} catch (JSchException | InterruptedException e) {
e.printStackTrace();
}
}
}
You can also try the following code
boolean statusFlag = true;
for(int i = 0;i < work.length;i++){
if(!work[i].contains("#")){
CommandLineInterface CLI = new CommandLineInterface();
String IP = null;
boolean AResult;
try {
AResult = CLI.Setting(work[i],"start"); //true or false
if(!AResult){
statusFlag = false;
}
} catch (JSchException | InterruptedException e) {
e.printStackTrace();
}
}
}
if(statusFlag){
result.setstatus("success");
}else{
result.setstatus("fail");
}
}

java websockets onMessage return InputStream to frontend javascript

I have come across a few posts, none of which has really answered my question, I have also been in the process of raising the question but putting it off only to research more dead ends...
So here is the issue, using j2ssh libraries to make ssh connections :
#OnMessage
public String handleOpen(Session usersession) {
System.out.println("Client is now connected.")
properties = new SshConnectionProperties();
properties.setHost(host)
properties.setPort(sshPort)
ssh.connect(properties, new IgnoreHostKeyVerification())
int result=0
PasswordAuthenticationClient pwd = new PasswordAuthenticationClient()
pwd.setUsername(username)
pwd.setPassword(password)
result = ssh.authenticate(pwd)
if(result == 4) {
isAuthenticated=true
}
// Evaluate the result
if (isAuthenticated) {
session = ssh.openSessionChannel()
SessionOutputReader sor = new SessionOutputReader(session)
if (session.requestPseudoTerminal("gogrid",80,24, 0 , 0, "")) {
if (session.startShell()) {
ChannelOutputStream out = session.getOutputStream()
session.getOutputStream().write("${usercommand} \n".getBytes())
println "--------------------------------authenticated user"
handleMessage(session.getInputStream(),usersession)
}
}
}
}
#OnMessage
public void handleMessage(InputStream stream, Session usersession) {
try {
usersession.getBasicRemote().sendText('SOMETHING')
usersession.getBasicRemote().sendObject(stream)
//return stream
} catch (IOException e) {
}
}
What I would like to do is for handleMessage to return the entire inputStream
Then within the javascript on the client's webpage to recieve that input stream :
...
webSocket.onmessage=function(message) {processMessage(message);};
var THRESHOLD = 10240;
...
function processMessage(message) {
//webSocket.send(textMessage.value);
//textMessage.value="";
messagesTextarea.value +=" woot woot woot\n";
if(message.data instanceof ArrayBuffer) {
var wordarray = new Uint16Array(message.data);
for (var i = 0; i < wordarray.length; i++)
{
console.log(wordarray[i]);
wordarray[i]=wordarray[i]+1;
}
messagesTextarea.value +=""+wordarray.buffer+"\n"
}else{
messagesTextarea.value +=""+message.data+"\n"
}
/*
setInterval( function() {
//messagesTextarea.value +=" Receive from Server ===> "+ message.data +"\n";
if (webSocket.bufferedAmount < THRESHOLD) {
if ((message.data != null)&&(message.data !="")) {
messagesTextarea.value +=" got from Server ===> ("+message.data+")";
}
} }, 5000);
*/
}
The objective is to launch ssh connection (no input really required - although with input would be of benefit for further client calls...
Once connected to run
handleMessage(session.getInputStream(),usersession)
This then returns the stream from the connection back to the javascript frontend.
At the moment I can see a connection to handleMessage but nothing is being returned to javascript frontend...
So I guess its related to how do you stream inputstreams via a javascript frontend.....
Ive actually got it working - up for lots of testing at the momemnt:
Java Endpoint:
#OnMessage
public void handleMessage(String message, Session usersession) {
InputStream input=session.getInputStream()
byte[] buffer=new byte[255]
int read;
int i=0
def pattern = ~/^\s+$/
while((read = input.read(buffer)) > 0) {
String out1 = new String(buffer, 0, read)
def m=pattern.matcher(out1).matches()
if (m==false) {
usersession.getBasicRemote().sendText(out1)
}
}
}
Front end Java script (note the call is not hitting array if call )
function processMessage(message) {
if(message.data instanceof ArrayBuffer) {
var wordarray = new Uint16Array(message.data);
for (var i = 0; i < wordarray.length; i++) {
console.log(wordarray[i]);
wordarray[i]=wordarray[i]+1;
}
messagesTextarea.value +=""+wordarray.buffer+"\n"
}else{
messagesTextarea.value +=""+message.data+"\n"
}
}

Categories