Connect to remote server via telnet and update a file programmatically - java

I want to change the settings of a PROROUTE wireless cellular router (H685) from the web application.
The only way to change the settings, is to login to the router via telnet and change a file in the editor (i.e. vi) and reboot.
I want to do it programmatically from server side using JAVA,
I can connect to the router and send command, using TelnetClient
Here is the sample code to connect to the router via telnet and send command
public class Test
{
private TelnetClient telnet = new TelnetClient();
private InputStream in;
private PrintStream out;
private String prompt = "#";
public Test(String server, String user, String password) {
try {
// Connect to the specified server
telnet.connect(server, 23);
// Get input and output stream references
in = telnet.getInputStream();
out = new PrintStream(telnet.getOutputStream());
// Log the user on
readUntil("Login:");
write(user);
readUntil("Password:");
write(password);
// Advance to a prompt
readUntil(prompt + " ");
} catch (Exception e) {
e.printStackTrace();
}
}
public String readUntil(String pattern) {
try {
char lastChar = pattern.charAt(pattern.length() - 1);
StringBuffer sb = new StringBuffer();
boolean found = false;
char ch = (char) in.read();
while (true) {
System.out.print(ch);
sb.append(ch);
if (ch == lastChar) {
if (sb.toString().endsWith(pattern)) {
return sb.toString();
}
}
ch = (char) in.read();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void write(String value) {
try {
out.println(value);
out.flush();
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
}
}
public String sendCommand(String command) {
try {
write(command);
return readUntil(prompt + " ");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void disconnect() {
try {
telnet.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
Test telnet = new Test("192.168.1.1", "username", "pwd");
telnet.sendCommand("ls");
telnet.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
But I have to update the file in the editor.
Send command to open the file in vi
$vi /flash/.disable_fun_list
function_dtu:
function_wifi:
function_gps:
.
.
.
.
function_wifi:on (this line needs to be changed)
and then send command to restart the router.
$reboot
Any idea, how this can be done.

What you're thinking to do sounds a terrible idea.
I feel there is no need to open this file in vi editor. In such cases, people generally suggest to create a temporary file and replace it with the original.
Suggested approach :
Open the file which you want to modify using BufferedReader on top of FileReader.
Modify the string, if you've to replace the currently read line; if not, then simply proceed to step 3.
Now, once you've string ready(whether changed OR unchanged) to be written to a file, then create a temporary file, and write the read string(line) to this temporary file.
Once, you're done with all the line of the original file, then close the BufferedReader, and delete(or, better rename to something else) the original file. Rename the temp file to the original filename, and move this temp file to the location of the original file from where you've copied(and modified) the content!
Code should flow like :
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader("C:\\testing.txt"));
while ((sCurrentLine = br.readLine()) != null) {
//Step 2 : do modification with the string read
//Step 3 : write the final modified string inside a temp file.
// Step 4 : close the br, and rename/delete the old file; rename the temp file to this original file.
}

you can use vi from command line without actually opening the vi as an app
you can pass args to vi to do a string replace for what you need
and you can pass args to save the file, plus the file path of course.
so you might end up executing this command via telnet connection
vi -c "%s/function_wifi:on/function_wifi:off/g|wq" /path/to/config/file
this will replace the string function_wifi:on with function_wifi:off and save the file.
simply then send a reboot command.
for more check this link

change above program to
private String prompt = ">";
instead of
private String prompt = "#";

Related

Java program one process per user on Microsoft Server

I receive bug to fix. Somebody write program which call printing document from other app. Jar with this program is on microsoft server for a few users. Problem is when one of user want print and other too in the same moment. Fox example user1 click print and have print preview, at the same moment user2 do the same action and he don't have print preview, because print prieview of document user2 is displayed on screen user1. I don't know where is bug. Maybe main app call the same instance of jar or the use the same process. Here is my code of method which is called when user click print.
public void openCreatedFile() {
String filePath = "file:///" + findNewlyCreatedFile().replace("\\", "/");
try {
if (xContext != null)
System.out.println("Opening file ...");
xMCF = xContext.getServiceManager();
Object oDesktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext);
xCLoader = UnoRuntime.queryInterface(com.sun.star.frame.XComponentLoader.class, oDesktop);
com.sun.star.beans.PropertyValue[] szEmptyArgs = new com.sun.star.beans.PropertyValue[0];
xComp = xCLoader.loadComponentFromURL(filePath, "_blank", 0, szEmptyArgs);
System.out.println(filePath);
xDoc = UnoRuntime.queryInterface(com.sun.star.text.XTextDocument.class, xComp);
xContext = null;
} catch (Exception e) {
e.printStackTrace(System.err);
Thread.currentThread();
}
}
You must change your BootstrapSocketConnector. Here is solution:
for(int i = 8100; i<=65535 ; i++){
if(available(i)){
libre.xContext = BootstrapSocketConnector.bootstrap(libre.oooExeFolder, "localhost", i);
System.out.println(i);
break;
}
}
8100 is for example, here you must use your port which is using to connection.
And for example method available() where you check closest available port:
private static boolean available(int port) {
try{
Socket ignored = new Socket("localhost", port);
return false;
} catch (IOException ignored) {
return true;
}
}

RandomAccessFile.seek() not working on Linux

I am using some sort of tail -f implementation to tail a file for changes (pretty much like this ). For this I am using a RandomAccessFile, periodically check if the file length has increased and if so, seek and read the new lines (everything happening in a separate thread of the FileTailer).
Now, everything is working as expected on Windows, but I tested my program on Linux and it does not work as expected. Here is the run()-method of the FileTailer class. Specifically where it fails on linux is the part where file.seek(filePointer) gets called and then file.readLine(), of which the latter surprisingly returns NULL (although the filePointer gets incremented correctly if I append content to the file getting tailed at runtime).
public void run() {
// The file pointer keeps track of where we are in the file
long filePointer = 0;
// Determine start point
if(startAtBeginning){
filePointer = 0;
}
else {
filePointer = logfile.length();
}
try {
// Start tailing
tailing = true;
RandomAccessFile file = new RandomAccessFile(logfile, "r");
while(tailing) {
// Compare the length of the file to the file pointer
long fileLength = logfile.length();
System.out.println("filePointer = " + filePointer + " | fileLength = " + fileLength);
if(fileLength < filePointer) {
// Log file must have been rotated or deleted;
// reopen the file and reset the file pointer
file = new RandomAccessFile(logfile, "r");
filePointer = 0;
}
if(fileLength > filePointer) {
// There is data to read
file.seek(filePointer);
String line = file.readLine();
System.out.println("new line = " + line);
while(line != null){
if(!line.isEmpty())
try {
fireNewFileLine(line);
} catch (ParseException e) {
e.printStackTrace();
}
line = file.readLine();
}
filePointer = file.getFilePointer();
}
// Sleep for the specified interval
sleep(sampleInterval);
}
// Close the file that we are tailing
file.close();
}
catch(InterruptedException | IOException e){
e.printStackTrace();
}
}
Like I said, everything is working as it should on Windows, but on Linux the String variable "line" is NULL after it should have been filled with the newly appended line, so fireNewLine gets called on NULL and everything goes to crap.
Does anyone have an idea why this happens on Linux Systems?
You don't need all this, or RandomAccessFile. You are always at the end of the file. All you need is this:
public void run() {
try {
// Start tailing
tailing = true;
BufferedReader reader = new BufferedReader(new FileReader(logfile));
String line;
while (tailing) {
while ((line = reader.readLine() != null) {
System.out.println("new line = " + line);
if(!line.isEmpty()) {
try {
fireNewFileLine(line);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
// Sleep for the specified interval
sleep(sampleInterval);
}
// Close the file that we are tailing
reader.close();
} catch(InterruptedException | IOException e) {
e.printStackTrace();
}
}
with maybe some provision for reopening the file.
E&OE

Gdx.files.internal(...) wrapper not working correctly

I made a wrapper ConfigurationFile class to help handle Gdx.files stuff, and it worked fine for a long time, but now it's not working, and I don't know why.
I have two of the following two methods: internal(...) and local(...). The only difference between the two is handling the load from arguments from (File folder, String name) and (String path).
-Snip Now Unnecessary Information-
UPDATE
After more configuring, I came to find out that they're not behaving the same. I have an assets/files/ folder that Gdx.files.internal(...) will access fine, but ConfigurationFile.internal(...) will access files/, and they're set up the same way. I'll give you the two pieces of code that I used for testing.
Using Gdx.files.internal(...) directly (works as expected):
FileHandle handle = Gdx.files.internal("files/virus_data");
BufferedReader reader = null;
try {
reader = new BufferedReader(handle.reader());
String c = "";
while ((c = reader.readLine()) != null) {
System.out.println(c); // prints out all 5 lines on the file.
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Using ConfigurationFile.internal(...):
// First part, calls ConfigurationFile#internal(String path)
ConfigurationFile config = ConfigurationFile.internal("files/virus_data");
// ConfigurationFile#internal(String path)
public static ConfigurationFile internal(String path) {
ConfigurationFile config = new ConfigurationFile();
// This is literally calling Gdx.files.internal("files/virus_data");
config.handle = Gdx.files.internal(path);
config.file = config.handle.file();
config.folder = config.file.getParentFile();
config.init();
return config;
}
// ConfigurationFile#init()
protected void init() {
// File not found.
// Creates a new folder as a sibling of "assets"
// Creates a new file called "virus_data"
if (!folder.exists()) folder.mkdirs();
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
} else loadFile();
}
// ConfigurationFile#loadFile()
protected void loadFile() {
BufferedReader reader = null;
try {
reader = new BufferedReader(handle.reader());
String c = "";
while ((c = reader.readLine()) != null) {
System.out.println(c);
if (!c.contains(":")) continue;
String[] values = c.split(":");
String key = values[0];
String value = values[1];
if (values.length > 2) {
for (int i = 2; i < values.length; i++) {
value += ":" + values[i];
}
}
key = key.trim();
value = value.trim();
mapValues.put(key, value);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
What I'm having trouble understanding is what's the difference between these two ways that it is causing my ConfigurationFile to create a new File in a folder that is a sibling of assets. Could someone tell me why this is happening?
My suggestion is not to use
Gdx.files.internal(folder + "/" + name);
If you have to use the File api, do it this way:
Gdx.files.internal(new File(folder, name).toString());
This way you avoid weird things that could be happening with path separators.
If Gdx maybe needs relative paths for some reason (perhaps relative to some Gdx internal home directory), you could use NIO to do something like
final Path gdxHome = Paths.get("path/to/gdx/home");
//...
File combined = new File(folder, name);
String relativePath = gdxHome.relativize(combined.toPath()).toString();
Okay, so after intense testing, I found out the problem, which I found to be ridiculous.
Since the file is Internal, that means a new File(...) reference can't be properly made to it, but instead it's an InputStream (if I'm correct), but anyways, using the method FileHandle#file() on an Internal file causes some kind of conversion for the path, so after removing anything that dealed with FileHandle#file() for an Internal file fixed it.

How to use java program to run command prompt commands?

this is my first time posting here, so I'm not really sure what to say/ask.
Anyways, I am trying to make a simple java program that runs command prompt commands from the java program, mainly used for ping flood (ping flooding myself).
Here is my current code
public class Core extends JFrame {
JTextField ipTextField;
int packets = 0;
boolean running = false;
public Core() {
super("Fatique");
Container container = getContentPane();
JButton bAttack = new JButton("Start Attack");
JButton bStop = new JButton("Stop Attack");
JPanel jPanel = new JPanel();
container.setLayout(new FlowLayout());
ipTextField = new JTextField("IP Address", 30);
container.add(ipTextField);
bAttack.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String input = ipTextField.getText();
String[] value = input.split(":");
int amountOfPackets = Integer.parseInt(value[1]);
exec("cmd /c" + input + " -t -n " + amountOfPackets);
running = true;
}
});
bStop.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
stop();
}
});
if(!running) {
jPanel.add(bAttack);
} else {
jPanel.add(bStop);
}
add(jPanel);
}
public void exec(String cmd) {
try {
Process p = Runtime.getRuntime().exec(cmd);
System.out.println(getOutput(p) + " - " + getPacketsSent());
} catch (IOException e) {
e.printStackTrace();
}
}
public String getOutput(Process p) {
String output = null;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
output = line;
packets++;
}
return output;
} catch (IOException e) {
System.err.println(e.getStackTrace());
}
return null;
}
public int getPacketsSent() {
return packets;
}
public void stop() {
exec("cmd /c break");
running = false;
}
public static void main(String[] args) {
Core c = new Core();
c.setSize(500, 300);
c.setVisible(true);
c.setResizable(false);
c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
c.setLocationRelativeTo(null);
}
I'm quite new at java, so that might not do what I want it to do.
What I want it to do is I enter an ip address in the textfield, and split it with ":", and after that the amount of packets, for instance
127.0.0.1:100
Though now when I try to use that ip and packet amount, it returns "null - 0" (from exec method), and I'm not even sure if it did anything related to ping.
What I am trying to accomplish is as I already said, ping flood myself, and then output whatever I get as response, though I have no idea if this code does anything even related to that, I mostly use logic when coding java.
public String getOutput(Process p) {
String output = null;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
output = line;
packets++;
}
return output;
} catch (IOException e) {
System.err.println(e.getStackTrace());
}
return null;
}
Could someone explain me why my code code is not working how I want it to work? Please don't judge, as I already said, I'm quite new to java programming.
EDIT: Here is a quick "informative" explanation of what I am trying to accomplish.
I type in an ip address and how many packets I want to send. In this explanation, I am using localhost ip, and 5 packets.
I start the attack. At this part, I want the program to run cmd prompt command
ping 127.0.0.1 -t -n 5
127.0.0.1 being the ip that I put in the textfield in my program, and 5 is the amount of packets I put in the textfield.
I started the attack, so this is what should happen in the command prompt:
The language is Finnish, but still the same thing.
This is the basic explanation of what I am trying to accomplish, hopefully someone understood and can help/tell why my code is not working, or is working but not printing the proper lines in eclipse console.
There is a problem with your getOutput method. It looks like you intend to collect every line of output. But in fact, since you are assigning line to output, you will only return the last line before the end of stream.
To fix this, change
output = line;
to
output += line + "\n";
Or to be more correct:
output += line + LINE_SEPARATOR;
where you previously declared the latter as:
final String LINE_SEPARATOR = System.getProperty("line.separator");
That doesn't directly explain why you are getting null, but that might be because the command you are running is writing output to the 'error' stream rather than the 'output' stream.
Try something like this:
try {
Runtime rt = Runtime.getRuntime();
Process p = rt.exec("ping 192.168.16.67");
InputStream in = p.getInputStream();
OutputStream out = p.getOutputStream ();
InputStream err = p.getErrorStream();
p.destroy();
} catch(Exception exc) {}
Then, you'll have to read the out variable to parse the ping command output continuously.
bAttack.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String input = ipTextField.getText();
String[] value = input.split(":");
int amountOfPackets = Integer.parseInt(value[1]);
try {
p=Runtime.getRuntime().exec("ping -n "+amountOfPackets+" "+value[0]);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
running = true;
}
Just a small modification of your code. get output is as:
public String getOutput(Process p) {
String output = null;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
output =output+ line+"\n";
packets++;
}
return output;
} catch (IOException e) {
System.err.println(e.getStackTrace());
}
return null;
}
Here output is JTextArea I have taken to display the output of PING process. I cannot show you the output because I lack reputation.
I don't know why first line is null. Anyway, it works.
Hope this help you. Have good time coding.

printing HL7 message in console

I'm passing an object to constructor and then adding parameters of this object to HL7.
ORU_R01 is the type of HL7.
When i print HL7 to console, only the last OBX is printed.
What is wrong with my code?
How can i write this HL7 message to socket?
Is there simpler way in java to handel HL7?
public class FlexSMessageHL7 {
private FileWriter writeHL7ToFile;
private PrismaflexSMessage sMessage;
private ORU_R01 message;
private int i = 0;
private OBX obx = null;
public FlexSMessageHL7(FlexSMessage sMessage) {
this.sMessage = sMessage;
this.message = new ORU_R01();
createHL7SMessage();
}
public void createHL7SMessage() {
// Populate the MSH Segment
MSH msh = message.getMSH();
try {
msh.getFieldSeparator().setValue("|");
msh.getEncodingCharacters().setValue("^~\\&");
msh.getDateTimeOfMessage().setValue(sMessage.getTime().toString());
msh.getSendingApplication().getNamespaceID().setValue(String.valueOf(sMessage.getMachID()));
} catch (DataTypeException e) {
e.printStackTrace();
}
// Populate the OBR Segment:time
OBR obr = message.getPATIENT_RESULT().getORDER_OBSERVATION().getOBR();
try {
obr.getObservationDateTime().setValue(String.valueOf(sMessage.getTime()));
} catch (DataTypeException e) {
e.printStackTrace();
}
// Populate the PID Segment:PatientId
PID pid = message.getPATIENT_RESULT().getPATIENT().getPID();
try {
pid.getPatientID().getIDNumber().setValue(sMessage.getPatID());
} catch (HL7Exception e) {
e.printStackTrace();
}
// Populate the OBX Segment:Param_Code, time, Measure_Value
while (i < sMessage.getMsgInfo()) {
for (PrismaflexSRecord sRecord : sMessage.getsRecordCollection()) {
try {
obx = message.getPATIENT_RESULT().getORDER_OBSERVATION().getOBSERVATION(i).getOBX();
obx.getSetIDOBX().setValue(String.valueOf(i));
obx.getObservationIdentifier().getIdentifier().setValue(sRecord.getParamCode());
obx.getDateTimeOfTheObservation().setValue(String.valueOf(sRecord.getTimeStamp()));
obx.getObservationIdentifier().getNameOfCodingSystem().setValue(String.valueOf(sRecord.getMeasureValue()));
i++;
} catch (HL7Exception e) {
e.printStackTrace();
}
}
}
try {
writeHL7ToFile = new FileWriter(File.createTempFile("prismaflexOutputFrom3001HL7", "txt", new File
("c:\\tmp\\prismaflex")));
writeHL7ToFile.write(message.getMSH().toString());
writeHL7ToFile.flush();
} catch (IOException e) {
e.printStackTrace();
}
// Now, Encode the message and look at the output
try {
Parser parser = new PipeParser();
String encodedMessage = parser.encode(message);
System.out.println("Printing HL7 Encoded Message:");
System.out.println(encodedMessage);
} catch (HL7Exception e) {
e.printStackTrace();
}
}
}
As Nicholas Orlowski pointed out, the problem is in the line ending characters, which according to the HL7 standard are CR characters which make a Windows command prompt only reset the cursor to the beggining of the line and overwrite it with next line's content. Therefore for console output You need to replace the line-endings with something else.
For a recent HL7 app using HAPI, which You also seem to be using, I made a little helper method to achieve this function:
private static String replaceNewlines(String input) {
return input.replaceAll("\\r", "\n");
}
The function can be used on all platforms, as it replaces the CR characters with the OS-specific newline character(s).
Then I can use it to output to console as follows:
LOGGER.trace("Generated message contents:\n" + replaceNewlines(outMessage.encode()));
In this case I am using log4j for logging to console, not simple console printout, but the problem was the same for me.
Hope it helps!
Have you considered using the HAPI? It is written for java, it's counter part nHAPI is written for .net as well. Details here:
http://hl7api.sourceforge.net/
I have had a similar problem in my python HL7py library. Many times the console doesn't like printing characters. I had to write a helper that changed CR to LF (line feed) to display the lines correctly. Hope that helps.
It won't display in the console but it will when you write to the file. Try looking at the variable in debug mode and writing it to a file.

Categories

Resources