FTP via PhoneGap - android

I would like to develop an FTP file system using PhoneGap.
Essentially i would like the user to be able to have a list of sites they can connect to and get the whole root directory for viewing and changing file names.
I can do this process with C# and .NET languages but have no knowledge on achieving this with PhoneGap.
Are there specific library's i could use?
Will i have to develop everything from scratch?
Is it possible to mix Native with PhoneGap?
What kind of security will i be looking at achieving here?
If you could answer one or all of these questions that is greatly appreciated!

A very easy way of achieving what you want in android is falling back to Native java code and use the Apache FTPClient class.
There is a very good easy to read plugin here. You can get it and take a look on how it works. Basically it uses the FTP client class and it has two built in methods to Upload a file and to Download a file from the server.
It's again dead easy to expand the Execute method to perform other actions like Rename and Delete :
Java Code:
public boolean execute (...) {
...
if (action.equals("get")) {
get(filename, url);
}
else if (action.equals("put")) {
put(filename, url);
}
else if (action.equals("delete")){
delete(filename,url);
} else if (action.equals("rename")){
rename(filename,url);
}
...
}
private void delete(String filename, URL url) throws IOException {
FTPClient f = setup(url);
f.deleteFile(extractFileName(url));
teardown(f);
}
private void rename(String newFilename, URL url) throws IOException {
FTPClient f = setup(url);
f.rename(extractFileName(url),newFilename);
buffOut.flush();
buffOut.close();
teardown(f);
}
And add these methods too on the javascript layer
FtpClient.prototype.delete = function(url, successCallback, errorCallback) {
return exec(successCallback, errorCallback, "FtpClient", "get", [" ", url]);
};
FtpClient.prototype.rename = function(newFilename, url, successCallback, errorCallback) {
return exec(successCallback, errorCallback, "FtpClient", "get", [newFilename, url]);
};
If you need instructions on how to use a phonegap plugin there is a good guide here. Basically you need to do the follwowing:
Write your java code
Write your javascript code and using the exec Method call the native layer
Add your plugin to res/xml/config
Specifically for the plugin I posted above, in the github readme you can see the instructions on how to install that plugin.

Related

How to hide API URL and parameters in Android APP?

I'm curious to know that without commercial product for obfuscation, is there any way where I can store API url and parameters safely which cannot be compiled in reverse engineering? I have tried all my apps and their API url and code is easy to read. I'm concerned about security.
Hide Url in Environmental variables,BuildConfig and Android Studio
One simple way to avoid this bad practice is to store your values
inside an environmental variable, so only your machine knows it, then
read this values in some way and inject them in your code at build
time. Let’s see how to do that using Android Studio, Gradle, and
BuildConfig.
First, we need to create these environmental vars. In Linux and Mac,
create or edit the file ~/.gradle/gradle.properties (pay attention to
the actual Gradle User Home directory position) and add some values:
WEBServiceBaseURL="http://192.168.2.102:2323/"
WEBServiceBaseSMSURL="https://www.example.com/"
Second, in your module’s build.gradle file, add these lines
//Add these lines
def Base_URL = '"' + WEBServiceBaseURL + '"' ?: '"Define BASE URL"';
def SMS_Base_URL = '"' + WEBServiceBaseSMSURL + '"' ?: '"Define SMS BASE URL"';
android.buildTypes.each { type ->
type.buildConfigField 'String', 'Base_URL', WEBServiceBaseURL
type.buildConfigField 'String', 'SMS_Base_URL', WEBServiceBaseSMSURL
}
Use in Java File Like
BuildConfig.Base_URL it will return URL String
public static Retrofit getClient() {
if (retrofit==null) {
retrofit =new Retrofit.Builder()
.baseUrl(BuildConfig.Base_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
I found a solution to hide base url to keep api secured with NDK. Keep base64 encoded string inside cpp file and call that from java class and decode base64.
Include c++ (NDK) support to your project. You can include this to your new or old project.
Your cpp file name can be like (native-lib.cpp)
Search online base64 encoder and encode your base url. Now keep encoded string inside cpp file
Inside cpp file sample code is like:
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_touhidapps_MyProject_utils_MyConstants_baseUrlFromJNI(JNIEnv *env, jobject) {
std::string mUrl = "aHR0cDovL2FwaS5leGFtcGxlLmNvbS8="; //"http://api.example.com/";
return env->NewStringUTF(mUrl.c_str());
}
Inside MyConstants.java class: (where I kept all api urls.)
// load c++ library
static {
System.loadLibrary("native-lib");
}
public static native String baseUrlFromJNI();
// decode base64 to a string and get normal url
public static String getSecureBaseUrl() {
String mUrl = baseUrlFromJNI();
try {
String text = new String(Base64.decode(mUrl, Base64.DEFAULT), "UTF-8");
return text;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
mUrl = "http://demo.example.com/"; // don't change this link. This will not execute normally, if exception happens then it will return a demo url.
return mUrl;
}
Now you can get your original url like below:
public static final String API_BASE = "" + getSecureBaseUrl();
Your question is not ideal for the StackOverflow as the topic is too broad and primarily opinion based. However, I thought I can share some of my thoughts as an answer here.
Hiding API urls with code obfuscation is definitely a good idea and it may work in some cases as well if you want to hide those. You might consider encrypting the API url in your code as well and store the encrypted url in your SharedPreferences or in local storage which needs to be decrypted again each time when you're using your API url to call a web service.
But none of these can't ensure that your API urls are uncrackable. If someone really wants to get your API urls s/he can easily get those by tracking the network that you're using to call the web services.
So encrypting API urls and obfuscating the variable names to hide the API urls will not work in most of the cases as you expected. And yes, I don't see any security breach in getting your API urls either. Because, the API server should be designed in a way that it can block unwanted service calls an attacker is making through an API. You might consider thinking of setting up a firewall in your host machines or can setup a basic authentication protocol which will protect your data. There are a lot of ways to prevent these security breach activities. You might also consider reading this article which I found useful to get a heads-up on how you can protect your APIs to be abused.
Hope that helps.

Unable to find exact Class name for finding Comments of a URL using jsoup

I am working in Android and using Jsoup for cwaling some data from internet. I am unable to find the exact class name where the comment lies in the below defined code. I tried with disqus_thread , dsq-content,ul-dsq-comments and dsq-comment-body by going to the source page of url but not any one returned the comments.
public static void main(String[] args) {
Document d;
Elements lin = null;
String url = "http://blogs.tribune.com.pk/story/39090/i-hate-materialistic-people-beta-but-i-love-my-designer-clothes/";
try {
d = Jsoup.connect(url).timeout(20*1000).userAgent("Chrome").get();
lin = d.getElementsByClass("dsq-comment-body");
System.out.println(lin);
} catch (IOException e) {
e.printStackTrace();
}
int i=0;
for(Element l :lin){
System.out.println(""+i+ " : " +l.text());
i++;
}
}
That's because the HTML that makes up the comments is generated dynamically after the page has been loaded, using Javascript. When the page is loaded the comment HTML doesn't exist, so Jsoup cannot retrieve it.
To get hold of the comments you have 3 options:
1) Use a web-crawler that can execute javascript. Selenium Webdriver (http://www.seleniumhq.org/projects/webdriver/) and PhantomJS (http://phantomjs.org/) are popular options here. The former works by hooking into a browser implementation (e.g. Mozilla Firefox) and opening the browser programmatically. The latter does not open a browser and executes the javascript by using Webkit instead.
2) Intercept the network traffic when opening the site (here you can probably use your browser's built-in network tab) and find the request that fetches the comments. Make this request yourself and extract the relevant data to your application. Bear in mind that this will not work if the server serving the comments requires some kind of authentication.
3) If the comments are served by a specialized provider with an openly accessible API, then it might be possible to extract them through this API. The site you linked to uses Disqus to handle the comment section so it might be possible to hook into their API and fetch them this way.

Selendroid as a web scraper

I intend to create an Android application that performs a headless login to a website and then scrape some content from the subsequent page while maintaining the logged-in session.
I first used HtmlUnit in a normal Java project and it worked just fine. But later found that HtmlUnit is not compatible with Android.
Then I tried JSoup library by sending HTTP “POST” request to the login form. But the resulting page does not load up completely since JSoup won't support JavaScript.
I was then suggested to have a look on Selendroid which actually is an android test automation framework. But what I actually need is an Html parser that supports both JavaScript and Android. I find Selendroid quite difficult to understand which I can't even figure out which dependencies to use.
selendroid-client
selendroid-standalone
selendroid-server
With Selenium WebDriver, the code would be as simple as the following. But can somebody show me a similar code example for Selendroid as well?
WebDriver driver = new FirefoxDriver();
driver.get("https://mail.google.com/");
driver.findElement(By.id("email")).sendKeys(myEmail);
driver.findElement(By.id("pass")).sendKeys(pass);
// Click on 'Sign In' button
driver.findElement(By.id("signIn")).click();
And also,
What dependencies to add to my Gradle.Build file?
Which Selendroid libraries to import?
Unfortunately I didn't get Selendroid to work. But I find a workaround to scrape dynamic content by using just Android's built in WebView with JavaScript enabled.
mWebView = new WebView();
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new HtmlHandler(), "HtmlHandler");
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (url == urlToLoad) {
// Pass html source to the HtmlHandler
WebView.loadUrl("javascript:HtmlHandler.handleHtml(document.documentElement.outerHTML);");
}
});
The JS method document.documentElement.outerHTML will retrieve the full html contained in the loaded url. Then the retrived html string is sent to handleHtml method in HtmlHandler class.
class HtmlHandler {
#JavascriptInterface
#SuppressWarnings("unused")
public void handleHtml(String html) {
// scrape the content here
}
}
You may use a library like Jsoup to scrape the necessary content from the html String.
I never had used Selendroid so I'm not really sure about that but searching by the net I found this example and, according to it, I suppose that your code translation from Selenium to Selendroid would be:
Translation code (in my opinion)
public class MobileWebTest {
private SelendroidLauncher selendroidServer = null;
private WebDriver driver = null;
#Test
public void doTest() {
driver.get("https://mail.google.com/");
WebElement email = driver.findElement(By.id("email")).sendKeys(myEmail);
WebElement password = driver.findElement(By.id("pass")).sendKeys(pass);
WebElement button = driver.findElement(By.id("signIn")).click();
driver.quit();
}
#Before
public void startSelendroidServer() throws Exception {
if (selendroidServer != null) {
selendroidServer.stopSelendroid();
}
SelendroidConfiguration config = new SelendroidConfiguration();
selendroidServer = new SelendroidLauncher(config);
selendroidServer.launchSelendroid();
DesiredCapabilities caps = SelendroidCapabilities.android();
driver = new SelendroidDriver(caps);
}
#After
public void stopSelendroidServer() {
if (driver != null) {
driver.quit();
}
if (selendroidServer != null) {
selendroidServer.stopSelendroid();
}
}
}
What do you have to add to your project
It seems that you have to add to your project the Selendroid standalone jar file. If you have doubts about how to add a external jar in an Android project you can see this question: How can I use external JARs in an Android project?
Here you can download the jar file: jar file
Also, it seems that it is not enough just to add the jar file to your project. You should add too the selendroid-client jar file of the version of standalone that you have.
You can download it from here: client jar file
I expect it will be helpful for you!
I would suggest you use WebdriverIO since you want to use Javascript.
It uses NodeJs so it will be easy to require other plugins to scrape the HTML.
Appium is also an alternative but it's more focused on front-end testing.

How to determine URL has valid domain or not or it's a valid url?

What i get in android native messaging, whenever we send a message to some one and in the text there is a url, android recognizes that and underlined it showing it as a link, it does that for many domains, like .us,.uk,.dk,.ch and all others valid.
Even we send jhjh.us without 'www' or 'http' it recognises it as link.
and if the domain is wrong it doesn't do any thing.
I want the same thing, I tried using pattern
(((https?|ftp|file)://)|(www\\.))"+ "[-a-zA-Z0-9+&##/%?=~_|!:,.;]*[-a-zA-Z0-9+&##/%=~_|]
it does a good but in domain it didn't help. Also tried using URLUtil.isValidUrl() but of no use,
Can anyone give me some idea regarding this.
You can try this
public boolean isURL(String url)
{
try {
new URL(url);
return true;
} catch (MalformedURLException e) {
return false;
}
}
U can use the Use UrlValidator to validate the URL
Considering you are using Class UrlValidator
UrlValidator urlValidator = new UrlValidator();
urlValidator.isValid("http://Test Link!");
There are several properties that you can set to control how this class behaves, by default http, https, and ftp are accepted.

Dropbox Sharing file URL

I am developing an application for Android and which uses Dropbox for organizing the files. I am exploring the Dropbox API but its description and help is limited, as there is no documentation for the Dropbox API.
I still would like to manage the files to some functionality, for example placing a file and getting a file from Dropbox. Now the problem is when I put some files in Dropbox public folder and I need a URL to share to my contacts in the application. But in the API I could not find any function that returns the web URL of the file to share (Just like in the Deskotop interface of Dropbox, a user can get a Shared URL to send to friends).
Could someone help me figure out how to share that file with contacts in the Application?
Or any other way to share a file using Dropbox Android API?
According to changes made on DropBox metioned here: https://www.dropbox.com/help/16/en
There would be no more Public folders, instead access to files can be done via Share Link.
If you use Android DropBox Core Api then shared link can be retrieved this way:
// Get the metadata for a directory
Entry dirent = mApi.metadata(mPath, 1000, null, true, null);
for (Entry ent : dirent.contents) {
String shareAddress = null;
if (!ent.isDir) {
DropboxLink shareLink = mApi.share(ent.path);
shareAddress = getShareURL(shareLink.url).replaceFirst("https://www", "https://dl");
Log.d(TAG, "dropbox share link " + shareAddress);
}
}
UPDATE: 2014/07/20 by Dheeraj Bhaskar
Use the following helper function alongwith the above function.
Since DropBox started to send shortened links it is little bit more problematic to get proper link.
For now, I am using this method :
We simply load the URL, follow the redirects and get the new URL.
String getShareURL(String strURL) {
URLConnection conn = null;
String redirectedUrl = null;
try {
URL inputURL = new URL(strURL);
conn = inputURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
System.out.println("Redirected URL: " + conn.getURL());
redirectedUrl = conn.getURL().toString();
is.close();
} catch (MalformedURLException e) {
Log.d(TAG, "Please input a valid URL");
} catch (IOException ioe) {
Log.d(TAG, "Can not connect to the URL");
}
return redirectedUrl;
}
Note: All of this should be done of course in AsyncTask or Thread. This will produce proper links ready to download
Update 2014/07/25: Change in dropbox share URLs
A heads-up on the kind of URLs to expect
From the Dropbox team:
We wanted to give you a heads up about an upcoming change to the URL
structure of Dropbox shared links. While not part of the API, the
change could affect apps that manipulate the URLs returned from the
/shares endpoint or the "preview" link type returned by the Chooser
Drop-in.
Links returned will now have a ?dl=0 appended to them.
E.g., instead of
https://www.dropbox.com/s/99eqbiuiepa8y7n/Fluffbeast.docx, you'll
receive URLs
like this link
https://www.dropbox.com/s/99eqbiuiepa8y7n/Fluffbeast.docx?dl=0.
A useful thread in the Dropbox forums:
http://forums.dropbox.com/topic.php?id=37700&replies=7#post-326432
IF The public link for a file is always
dl.dropbox.com/u/<your users uid>/<path under /Public>/filename
then we can just use the API to get and build the public URL in the code.
Perhaps this may also help: Upload a file to Dropbox and copy public address. This script upload a file to your /Public directory and use your accound
UID to build it's public URL. Then, it echoes the URL to the console.
https://github.com/sylvainfilteau/dropbox-api-command/commit/6aa817c79220c5de4ff5339cd01ea8b528bcac36
I am not there yet in my Dropbox interface implementation, but this is one of the functions I need to develop. More in one or two days I hope.
I believe the url is as follows:
http://dl.dropbox.com/u/YOUR_DROPBOX_ID/YOUR_FILE_NAME

Categories

Resources