I'm using FTPClient of apache for getting size of specific file from my server. So, the error that I faced in android is 530 You aren't logged in. while my code is such below and I've tested it in pure Java. I don't know why this error occurred on Android but all things are okay in Java.
client.connect("my-server-ip");
client.login("username", "password");
client.setKeepAlive(true);
client.setFileType(FTP.BINARY_FILE_TYPE, FTP.BINARY_FILE_TYPE);
client.setFileTransferMode(FTP.BINARY_FILE_TYPE);
client.sendCommand("SIZE " + "file-path");
try {
sizeStr = client.getReplyString().trim();
this.M_fileData.M_contentLength = Long.parseLong(sizeStr.split(" ")[1]);
System.out.println(sizeStr);
} catch (NumberFormatException e) {
e.printStackTrace();
client.disconnect();
}
Java pure result is : 213 1757682, while android result is 530 You aren't logged in.
Could any one explain me how to solve this ?
Thanks in advance.
- First of all i want you to make sure you have given the android.permission.INTERNET permission.
Well for further reference, i am giving you the code that i used to Download music clip in my android application.
I have used the Apache's commons library
public void goforIt(){
FTPClient con = null;
try
{
con = new FTPClient();
con.connect("50.xx.xx.xx");
if (con.login("Adminxxxxx", "KUjWbk361wobbyl-xxxxxx"))
{
con.enterLocalPassiveMode(); // important!
con.setFileType(FTP.BINARY_FILE_TYPE);
String data = "/sdcard/vivek.m4a";
OutputStream out = new FileOutputStream(new File(data));
boolean result = con.retrieveFile("vivekm4a.m4a", out);
out.close();
if (result) Log.v("download result", "succeeded");
con.logout();
con.disconnect();
}
}
catch (Exception e)
{
Log.v("download result","failed");
e.printStackTrace();
}
}
Whenever 530 error code return it means your username or password is incorrect. And due to login failed you cant upload file.
Related
I have tried to build a http server to streaming video using HLS. I have process the response like below.
private void handleResponse(HttpExchange exchange, String fileNameValue) {
OutputStream responseStream = exchange.getResponseBody();
File file = new File(fileNameValue);
try {
String encoding = "UTF-8";
String response = FileUtils.readFileToString(file, encoding);
exchange.getResponseHeaders().set("Content-Type", "application/x-mpegURL");
exchange.getResponseHeaders().set("Accept-Ranges", "bytes");
exchange.getResponseHeaders().set("Cache-Control", "max-age=0, no-cache, no-store");
exchange.sendResponseHeaders(200, response.length());
responseStream.write(response.getBytes());
responseStream.flush();
responseStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
But the browsers always download the file instead of playing it. And VLC Media Player doesn't play it too.
I want to get the result like this.
Can you show me the way to do it? Some keywords for researching are also appreciated.
I have figured out that their website using xhr to send request so the file appears in the Network section.
I use hls.js after that and get the same result :)
im trying to send files to FTPS server
connection method: FTPS, ACTIVE, EXPLICIT
setFileType(FTP.BINARY_FILE_TYPE);
setFileTransferMode(FTP.BLOCK_TRANSFER_MODE);
Checking the reply string right after connect i got:
234 AUTH command ok. Expecting TLS Negotiation.
from here
234 Specifies that the server accepts the authentication mechanism specified by the client, and the exchange of security data is complete. A higher level nonstandard code created by Microsoft.
while trying to send file with storeFile or storeUniqeFile i get false
checking the reply string right after store file i got: 501 Server cannot accept argument.
what is weird i was able creating a directory to this client without any issues
with makeDirectory("test1");
i was trying both this links : link1 , link2
FOR EXAMPLE when i was trying to use ftp.enterLocalPassiveMode(); before ftp.storeFile(destinationfile, in);
i got time out error .
Does anyone have any idea how to solve it ?
public static void main(String[] args) throws Exception {
FTPSProvider ftps = new FTPSProvider();
String json = "connection details";
DeliveryDetailsFTPS details = gson.fromJson(json, DeliveryDetailsFTPS .class);
File file = File.createTempFile("test", ".txt");
FileUtils.write(file, " some test", true);
try (FileInputStream stream = new FileInputStream(file)) {
ftps.sendInternal(ftps.getClient(details), details, stream, file.getName());
}
}
protected void sendInternal(FTPClient client, DeliveryDetailsFTPS details, InputStream stream, String filename) throws Exception {
try {
// release the enc
DeliveryDetailsFTPS ftpDetails = (DeliveryDetailsFTPS) details;
setClient(client, ftpDetails);
boolean isSaved = false;
try (BufferedInputStream bis = new BufferedInputStream(stream)) {
isSaved = client.storeFile(filename, bis);
}
client.makeDirectory("test1");
client.logout();
if (!isSaved) {
throw new IOException("Unable to upload file to FTP");
}
} catch (Exception ex) {
LOG.debug("Unable to send to FTP", ex);
throw ex;
} finally {
client.disconnect();
}
}
#Override
protected FTPClient getClient(DeliveryDetails details) {
return new FTPSClient(isImplicitSSL((DeliveryDetailsFTPS ) details));
}
protected void setClient(FTPClient client, DeliveryDetailsFTPS details) throws Exception {
DeliveryDetailsFTPS ftpDetails = (DeliveryDetailsFTPS ) details;
client.setConnectTimeout(100000);
client.setDefaultTimeout(10000 * 60 * 2);
client.setControlKeepAliveReplyTimeout(300);
client.setControlKeepAliveTimeout(300);
client.setDataTimeout(15000);
client.connect(ftpDetails.host, ftpDetails.port);
client.setBufferSize(1024 * 1024);
client.login(ftpDetails.username, ftpDetails.getSensitiveData());
client.setControlEncoding("UTF-8");
int code = client.getReplyCode();
if (code == 530) {
throw new IOException(client.getReplyString());
}
// Set binary file transfer
client.setFileType(FTP.BINARY_FILE_TYPE);
client.setFileTransferMode(FTP.BLOCK_TRANSFER_MODE);
if (ftpDetails.ftpMode == FtpMode.PASSIVE) {
client.enterLocalPassiveMode();
}
client.changeWorkingDirectory(ftpDetails.path);
}
I have tried this solution as well didn't solve the problem:
they only way i was able send file is with FileZilla and it is using FTPES .
But i need my Java code to do it . can anyone give me a clue
I have tried almost any possible solution offered on different websites could not make it work with Apache FTPS CLIENT ,
had to use a different class which worked like a charm here is a snippet:
com.jscape.inet.ftps Link
private Ftps sendWithFtpsJSCAPE(ConnDetails details, InputStream stream, String filename) throws FtpException, IOException {
Ftps ftp;
FtpConnectionDetails ftpDetails = FtpConnectionDetails details;
ftp = new Ftps(ftpDetails.getHost(), ftpDetails.getUsername(), ftpDetails.getPassword());
if (ftpDetails.getSecurityMode().equals(FtpConnectionDetails.SecurityMode.EXPLICIT)) {
ftp.setConnectionType(Ftps.AUTH_TLS);
} else {
ftp.setConnectionType(Ftps.IMPLICIT_SSL);
}
ftp.setPort(ftpDetails.getPort());
if (!ftpDetails.getFtpMode().equals(FtpMode.ACTIVE)) {
ftp.setPassive(true);
}
ftp.setTimeout(FTPS_JSCAPE_TIME_OUT);
ftp.connect();
ftp.setBinary();
ftp.setDir(ftpDetails.getPath());
ftp.upload(stream, filename);
return ftp;
}
I am attempting to upload via ftp a file, named "advancedsettings.xml" located in path "/storage/emulated/0/advancedsettings.xml" from my Android device. It doesn't seem to be working; the file does not upload and the following exception is thrown:
01-06 17:56:17.498 28084-28084/com.name.example.appname E/SmsReceiverīš android.os.NetworkOnMainThreadException
I discovered that basically, an application cannot attempt to perform a networking operation "on its main thread".
I am new at Java but I understand, following from this, I must implement "ASync"; I haven't understood how to implement it. Could somebody help describe this to me and how I might implement it in respect of the below code?
My code is as follows:
public class FtpUpload {
// use this method to upload the file using file path global var and ftp code,
//then return the link string.
//TO DO: UID file name to prevent file already exists overwrite on server?
public void total() {
FTPClient con = null;
String dest_fname = "advancedsettings.xml"; // Added to create a destination file with a dynamically created name (same as the file name in /sdcard/ftp/)
try
{
con = new FTPClient();
con.connect("ftp.domain.co.uk");
// Check your USERNAME e.g myuser#mywebspace.com and check your PASSWORD to ensure they are OK.
if (con.login("username", "password"))
{
con.enterLocalPassiveMode(); // important!
con.setFileType(FTP.BINARY_FILE_TYPE);
String data = "/storage/emulated/0/advancedsettings.xml";
FileInputStream in = new FileInputStream(data);
boolean result = con.storeFile(dest_fname, in);
in.close();
if (result) Log.v("upload result", "succeeded");
con.logout();
con.disconnect();
} else { // This Error Log was created
// Create error log as a file
File log_file = new File("/storage/emulated/0/error.txt");
try {
FileWriter lfw = new FileWriter(log_file);
BufferedWriter lout = new BufferedWriter(lfw);
// Continue
lout.write("Upload Connection Failed!");
lout.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
Log.e("SmsReceiver", e1.toString());
}
}
}
catch (Exception e)
{
Log.e("SmsReceiver", e.toString());
}
}
Thank you in advance.
K
Shamefully I didn't initially come across this documentation on Async Tasks, which has proven invaluable.
With a bit of improv though, I got it working. I just modified my class as such:
private class FtpUpload extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
//code here
}
And used the following to call the above Async method:
new FtpUpload().execute();
Of course, you won't get very far with FTP networking without declaring the following user permissions in your manifest file (outside of the "application" tags):
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
I want to login to a https website with username and password, go to one url in that website and download the page at the url (and maybe parse contents of that page). I want to do this using only core Java apis and not htmlunit, jsoup etc. I got the below code to learn how to do this, but it does not show me how to login to a website. Please tell me how I can login, maintain a session and then finally close the connection.
Source - http://www.mkyong.com/java/java-https-client-httpsurlconnection-example/
import java.net.MalformedURLException;
import java.net.URL;
import java.security.cert.Certificate;
import java.io.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLPeerUnverifiedException;
public class HttpsClient{
public static void main(String[] args)
{
new HttpsClient().testIt();
}
private void testIt(){
String https_url = "https://www.google.com/";
URL url;
try {
url = new URL(https_url);
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
//dumpl all cert info
print_https_cert(con);
//dump all the content
print_content(con);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void print_https_cert(HttpsURLConnection con){
if(con!=null){
try {
System.out.println("Response Code : " + con.getResponseCode());
System.out.println("Cipher Suite : " + con.getCipherSuite());
System.out.println("\n");
Certificate[] certs = con.getServerCertificates();
for(Certificate cert : certs){
System.out.println("Cert Type : " + cert.getType());
System.out.println("Cert Hash Code : " + cert.hashCode());
System.out.println("Cert Public Key Algorithm : "
+ cert.getPublicKey().getAlgorithm());
System.out.println("Cert Public Key Format : "
+ cert.getPublicKey().getFormat());
System.out.println("\n");
}
} catch (SSLPeerUnverifiedException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}
}
private void print_content(HttpsURLConnection con){
if(con!=null){
try {
System.out.println("****** Content of the URL ********");
BufferedReader br =
new BufferedReader(
new InputStreamReader(con.getInputStream()));
String input;
while ((input = br.readLine()) != null){
System.out.println(input);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Every website manages logins differently. You will need to scout the website, find out how the session is maintained, and mimic the functions in such a way that the server can't tell that it is not a browser.
In general, a web server stores a secret hash in the cookie. Here is the process
Post a login and password to said url using HttpsURLConnection to send the form.
The server responds with a hash in a header that it wants stored in the cookie. Usually has session in the name.
Send requests back with the hash in the header in the correct value
All of the above can be done only using URL and HttpsURLConnection, but you will need to mimic a browser exactly to trick the server.
For scouting, I would recommend using a tool like fiddler. It captures all communication from the webserver and back, so that you can see exactly what is going on at the http level to mimic in your java code.
Here is an overview of fiddler. I have never looked at the logs. Fiddler has a sweet interface. The video is really boring, but it gives an overview of the interface. You want to look at the raw text view, and mimic that.
For your other question, owasp is a great resource for best practices. The reality is that there is a lot of insecure and bad code out there that does stuff that you would never expect. I have seen a server put the boolean value inside of a script tag to be stored as a javascript variable. You just have to carefully watch how the server changes the responses after you log in. For a popular website following best practices, they will use the above method.
I am uploading files(.cvs,.zip,.rar,.doc,.png,.jpg...) to ftp server. The strange is everything is successfully but I miss some data.
Does any body know why it happens and how to fix it?
public static void uploadWithCommonsFTP(File fileToBeUpload) {
FTPClient f = new FTPClient();
try {
f.connect(server.getServer());
f.login(server.getUsername(), server.getPassword());
f.changeWorkingDirectory("user");
f.setFileType(FTP.BINARY_FILE_TYPE);
f.setFileTransferMode(FTP.BINARY_FILE_TYPE);//this is part of Mohammad Adil's solutions
f.enterLocalPassiveMode();
ByteArrayInputStream in = new ByteArrayInputStream(FileUtils.readFileToByteArray(fileToBeUpload));
boolean reply = f.storeFile(fileToBeUpload.getName(), in);
if(!f.completePendingCommand()) {
f.logout();
f.disconnect();
System.err.println("File transfer failed.");
System.exit(1);
}
if(reply){
JOptionPane.showMessageDialog(null,"uploaded successfully.");
}else{
JOptionPane.showMessageDialog(null,"Upload failed.");
}
}
//Logout and disconnect from server
in.close();//this is part of Mohammad Adil's solutions
f.logout();
f.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
It's often forgotten that FTP has two modes of operation - one for text files and the other for binary(jpg,csv,pdf,zip) files.
Your code doesn't work because the default transfer mode for FTPClient is FTP.ASCII_FILE_TYPE. You just need to update the configuration to transfer in binary mode.
Add this in your code :
f.setFileTransferMode(FTP.BINARY_FILE_TYPE);
just put that line after f.setFileType(FTP.BINARY_FILE_TYPE);
and it should work then.
EDIT:
You are not closing inputStream in your code,Just call in.close() before calling logout()