Android: showing a captcha from server - android

For my application I need to use a captcha for verification. I am using this link for it: http://vocublablair.nl/webservices/send.php
It returns a string something like this: /webservices/simple-php-captcha.php?_CAPTCHA&t=0.59145200+1338304461
Then that link should be called, being: http://vocublablair.nl/webservices/simple-php-captcha.php?_CAPTCHA&t=0.59145200+1338304461
When I call this with the same HttpClient (so with the right session cookie) it gives the following error:
java.lang.IllegalArgumentException: Illegal character in query at index 94: http://vocublablair.nl/webservices/simple-php-captcha.php?_CAPTCHA&t=0.59145200+1338304461

best way is to generate your own captcha image because using third party resources may cause inconvenient for your customers.
for generating capthcha in android you could use this simple library :
http://simplecaptcha.sourceforge.net/

I solved the problem doing the following:
First of all the link I got back had to be HTML encoded using:
Html.fromHtml(String)
Calling the correct URL:
content = sb.toString(); //the fetched link
String myCookie = "";
//get session cookie from other call.
List<Cookie> cookies = ((DefaultHttpClient)httpClient).getCookieStore().getCookies();
for(Cookie c : cookies){
if(c.getName().equals("PHPSESSID")){
myCookie = c.getName() + "=" + c.getValue();
break;
}
}
URL url = new URL(Html.fromHtml("http://vocublablair.nl" + content).toString());
URLConnection connection = url.openConnection();
connection.setDoInput(true);
connection.setRequestProperty("Cookie", myCookie);
connection.connect();
Bitmap bit = BitmapFactory.decodeStream(new FlushedInputStream((InputStream) connection.getContent()));
I am using a FlushedInputStream. Read about it here: http://twigstechtips.blogspot.com/2011/10/android-loading-jpgpng-images-from-url.html

Related

Sending HttpURLConnection inputStream to WebResourceResponse not resulting in proper response for WebView

I'm trying to append the cors headers to a request made in an Android webview by a JavaScript fetch command in order to bypass cors. To do this I'm intercepting requests made in the WebView with the shouldInterceptRequest member function.
The code I have seems to be working except that the stream I'm getting from the HttpURLConnection doesn't seem to work with the stream required by the WebResourceResponse. The relevant code (inside shouldInterceptRequest function):
val url = URL("https://www.android.com")
val urlConnection: HttpURLConnection = url.openConnection() as HttpURLConnection
try {
var headers =
urlConnection.headerFields.mapValues { it.value.joinToString() }
headers = headers.toMutableMap()
headers["Access-Control-Allow-Origin"] = "*"
headers["Access-Control-Allow-Headers"] = "*"
headers["Access-Control-Allow-Credentials"] = "true"
// val inStream: InputStream = BufferedInputStream(urlConnection.inputStream) // Doesn't work
// val string = "hello world :)"
// val inStream = string.byteInputStream(charset = Charset.forName("UTF-8")) // Works when used as stream, sends "hello world :)" as response
return WebResourceResponse(
headers["Content-Type"],
if (urlConnection.contentEncoding === null) "UTF-8" else urlConnection.contentEncoding,
urlConnection.responseCode,
"OK",
headers,
urlConnection.inputStream
)
} finally {
urlConnection.disconnect()
}
The last argument of the WebResourceResponse needs to be a stream which will be sent to the Webview page. When using the urlConnection.inputStream I can see in Chrome devtools that the headers are set properly on the response, but the data fails to load.
When I replace the response stream with a string the solution works fine, and the webview receives the string correctly. My question is then why doesn't the stream from the HttpURLConnection work when given to the response object, and how do I make it work.
The solution I'm looking for should not only support text, but also binary data and streams.
As a side note I've also tried implementing the requestIntercept asynchronously, as mentioned here: How to get WebViewClient.shouldInterceptRequest invoked asynchronously, which changes the stream given to the response object, however this resulted in a very slow request followed by an android crash after the data had loaded and the request was done.
This isn't a duplicate of WebResourceResponse can't read full inputstream from HttpConnection (Android), the problem is different and the solution wouldn't work.
Entire code file: https://gist.github.com/RuurdBijlsma/2b52d80a4d74460ac2837ee55b0b933c in case that's helpful.

How to call a Youtube Data API through HTTPUrlConnection in Android with using headers?

I am trying to develop a part of my app in which i want to get video details for a keyword. I am using the search list API. I think I have an issue with the authorization. I am getting a 401. I have tried passing my authorization details.
I have tried the following code after going through a few resources online and I am current getting the java.io.FileNotFoundException at the line at which i get the Input Stream. The connection code that I am getting is a 401.
The given code is in the doInBackground of an AsyncTask.
String ytres="";
URL url;
HttpURLConnection urlConnection = null;
try {
Log.d("youtubedata","a1");
url = new URL("https://www.googleapis.com/youtube/v3/search?part=id&q=queen%20bohemian");
Log.d("youtubedata","a2");
Log.d("youtubedata","a");
urlConnection = (HttpURLConnection) url
.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setRequestProperty ("Authorization", "Bearer MYAPIKEY");
urlConnection.setRequestProperty ("Accept", "application/json");
Log.d("youtubedatanum",Integer.toString(urlConnection.getResponseCode()));
InputStream in = urlConnection.getInputStream();
InputStreamReader isw = new InputStreamReader(in);
int data = isw.read();
while (data != -1) {
char current = (char) data;
data = isw.read();
ytres=ytres+current;
System.out.print(current);
}
Log.d("youtubedata",ytres);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return ytres;
I do suspect the issue is in the way i have passed my API Key.
Please go through the API docs at Calling the API and at Search Endpoint.
You'll see that your URL does not contain the needed API key passed on as the key parameter.
It may also worth it to dug up Google's own sample Java implementation at Search.java. However, that code, due to the layer of library abstraction it uses, is not of immediate help since it obscures the way a client should work directly with the API.
For You-tube Data API error 401
Possible issue for unauthorized (401) can be
authorizationRequired
youtubeSignupRequired
Check You-tube Data API error doc Here.
Also confirm that you have follow THIS steps to integrate API.
Sample API Code you can find Here
Hope this can help you.

Android - Regex-Pattern for hidden html-input field's value

I'm pretty new/bad with regex-patterns, but this is what I want:
I've got a webpage with html, and somewhere on that page I have: <input name="__RequestVerificationToken" type="hidden" value="the_value_I_want" />
So, my question is: How can I get the value (the_value_I_want) of the hidden text field in Android?
I did make the HttpGet already (see code below), I just need to know the correct Pattern for this.
Code:
// Method to get the hidden-input value of the Token
private String getToken(){
String url = "http://myhost/Account/Login";
String hidden_token = "";
String response = "";
HttpGet get = new HttpGet(url);
try{
// Send the GET-request
HttpResponse execute = MainActivity.HttpClient.execute(get);
// Get the response of the GET-request
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while((s = buffer.readLine()) != null)
response += s;
}
catch(Exception ex){
ex.printStackTrace();
}
// Get the value of the hidden input-field with the name __RequestVerificationToken
Pattern pattern = Pattern.compile("<input name=\"" + TOKEN + "\" type=\"hidden\" value=\".\" />", Pattern.DOTALL);
Matcher matcher = pattern.matcher(response);
while(matcher.find())
hidden_token = matcher.group();
return hidden_token;
}
So, what should I replace the following line with?
Pattern pattern = Pattern.compile("<input name=\"" + TOKEN + "\" type=\"hidden\" value=\".\" />", Pattern.DOTALL);
Or should I also change something else?
Thanks in advance for the responses.
PS: For those wondering: I need this token to be able to Log-in using a Google-account with a POST-request, combined with the token I got from a Cookie.
Edit 1:
After reading the answer of this stackoverflow question I think it's better to not use a regex-pattern for the HTML page. Does anyone know a better solution (I would appreciate it if this better solution would be with a code sample).
Edit 2:
I tried using Illegal Argument's answer and added the Jsoup library. I did indeed manage to get the token by making the following changes to my code above:
Replace everything in the try { ... } with:
// Get the value of the hidden input-field with the name __RequestVerificationToken
Document doc = Jsoup.connect(url).get();
org.jsoup.nodes.Element el = doc.select("input[name*=" + TOKEN).first();
hidden_token = el.attr("value");
This does indeed get me the token of the hidden field, but now I have an entire new problem.. The token changed, because Jsoup opens a new session. So basically I can't use the Jsoup and are "forced" to use the already open DefaultHttpClient that I also use for the POST.
I will make a new question for this though, since my original answer was just bad questioning by myself (not providing all the details) and so I accept Illegal Argument's answer as the correct one (though it didn't solved my current problem, it might help others).
Try using Jsoup library. Its is a regex parser built for this purpose.

Android - Get hidden input value of html page using DefaultHttpClient

I already asked a similar question before, but wasn't providing enough details. So here is the "same" question, but this time more in-depth.
I've got a webpage with html, and somewhere on that page I have: <input name="__RequestVerificationToken" type="hidden" value="the_value_I_want" />
So, my question is: How can I get the value (the_value_I_want) of the hidden text field in Android, using HttpGet of an already open DefaultHttpClient connection?
My current code:
// Method to get the hidden-input value of the Token
private String getToken(){
String url = "http://myhost/Account/Login";
String hidden_token = "";
String response = "";
HttpGet get = new HttpGet(url);
try{
// Send the GET-request
HttpResponse execute = MainActivity.HttpClient.execute(get);
// Get the response of the GET-request
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while((s = buffer.readLine()) != null)
response += s;
content.close();
buffer.close();
// Get the value of the hidden input-field with the name __RequestVerificationToken
// TODO
}
catch(Exception ex){
ex.printStackTrace();
}
return hidden_token;
}
So, what should I add on the TODO-line?
Because the Token and Cookie only remain as long as the Session stays open, I can't use the Jsoup library for finding the hidden field (which I did by using the code below). Instead I need to use the already open DefaultHttpClient.
Jsoup code:
Document doc = Jsoup.connect(url).get(); // <- this opens a new session
org.jsoup.nodes.Element el = doc.select("input[name*=" + TOKEN).first();
hidden_token = el.attr("value");
Thanks in advance for the responses.
PS: For those wondering: I need this token to be able to Log-in using a Google-account with a POST-request, combined with the token I got from a Cookie.
Ok, lucky for me this was very simple. I just replaced Document doc = Jsoup.connect(url).get(); with Document doc = Jsoup.parse(html);
So in the code of the main post I replaced //TODO with:
Document doc = Jsoup.parse(response);
org.jsoup.nodes.Element el = doc.select("input[name*=" + TOKEN).first();
hidden_token = el.attr("value");
Edit 1:
I thought this did the trick, but it doesn't.. It still thinks there are two different Sessions opened.. :S
Does Jsoup.parse(...) open a new Jsoup.get-session behind the scenes?
Edit 2:
It's even worse.. Every time another page is opened on the website, another session is created and therefore another token is needed.. So I need to discuss some things with the creator of the website/web api hybrid and figure some things out.. Perhaps create a different log-in just for the Web API..
All in all I'm kinda frustrated right now, even though all the problems I've encountered are "solved"..

how to find operator name from website phone no. search page in android application?

I need to find operator name from phone no. using this website in my android application.
Requesting and parsing HTML in the application works fine.
When I query request string from the app:
address: .https://nummertjanster.pts.se/net/en/Nummerkapacitet/Enskiltnummer?&_rp/pts.SearchNumber_ndc=70&_rp/pts.SearchNumber_operator=Tele2+Sverige+AB&_rp/pts.SearchNumber_telnumber=4264128
I need to specify 'operator name' ..which is wierd I guess.
The problem is no matter which number (ndc-telnumber) I enter if I specify a operator name in the request string the resulting webpage shows that operator name.
Here are some numbers to test:
073-3355433 = Telenor Sverige AB
073-6107353 = Tele 2 Sverige AB
070-3999266 = TeliaSonera Sverige AB
073-2404070 = Glocalnet AB
How can I find the proper operator name for a specific number?
Thanks for your any help.
There are a couple of issues with the site that prevent things from working:
It needs a cookie for the POST to work.
The operator name is actually not returned as part of the page, it is returned as part of a location redirect (302).
This chunk of code does what you want (I was dodging work, so I actually tidied it up for you): it hits the main page, fetches/extracts the cookie returned, posts the area code and number to the website and then intercepts the Location header and pulls out the operator name. Note that the area code is not always 3-digits (so for example for 073-3355433 you would do String operatorName = findOperator("73","3355433");.
String findOperator(String ndc, String number)
{
String parameters = "action=search&ndc="+ndc+"&number="+number+"&search=S%F6k";
HttpURLConnection httpUrlConnection = null;
OutputStream outputStream = null;
InputStream inputStream = null;
int code = 0;
String response = null;
try {
java.net.URI u = new java.net.URI("https://nummertjanster.pts.se/net/sv/Nummerkapacitet/Enskiltnummer");
httpUrlConnection = (HttpURLConnection) u.toURL().openConnection();
httpUrlConnection.setConnectTimeout(7500);
httpUrlConnection.setReadTimeout(7500);
httpUrlConnection.setRequestMethod("GET");
httpUrlConnection.connect();
String cookie = httpUrlConnection.getHeaderField("Set-Cookie");
u = new java.net.URI("https://nummertjanster.pts.se/actionrequest/sv/Nummerkapacitet/Enskiltnummer?__ac_/pts.SearchNumber");
httpUrlConnection = (HttpURLConnection) u.toURL().openConnection();
httpUrlConnection.setConnectTimeout(7500);
httpUrlConnection.setReadTimeout(7500);
httpUrlConnection.setRequestProperty("Cookie", cookie);
httpUrlConnection.setRequestMethod("POST");
httpUrlConnection.setDoOutput(true);
httpUrlConnection.connect();
outputStream = httpUrlConnection.getOutputStream();
outputStream.write(parameters.getBytes("UTF-8"));
httpUrlConnection.setInstanceFollowRedirects(false);
try {
inputStream = httpUrlConnection.getInputStream();
} catch (IOException e) {
//andrologger.warn("An error occurred while POSTing to " + url, e);
}
code = httpUrlConnection.getResponseCode();
response = httpUrlConnection.getHeaderField("Location");
if(response != null){
response = response.split("&")[2].split("=")[1];
}
}catch(Exception e1){
android.util.Log.v("Configuration","Exception: "+e1.getMessage(), e1);
} finally {
closeQuietly(outputStream);
closeQuietly(httpUrlConnection);
}
return response;
}
Tested it on my phone and it works fine: let me know how it works for you.
It clearly doesn't work restfully. You'll have to find another way.
Perhaps imitate the form post that the page is doing: http://www.androidsnippets.com/executing-a-http-post-request-with-httpclient
EDIT this doesn't work
Pretty simple:
https://nummertjanster.pts.se/net/sv/Nummerkapacitet/Enskiltnummer?&__rp_/pts.SearchNumber_ndc=PUT_AREA_NUMBER_HERE&__rp_/pts.SearchNumber_operator=xxno_operatorxx&__rp_/pts.SearchNumber_telnumber=PUT_NUMBER_HERE
i.e.
https://nummertjanster.pts.se/net/sv/Nummerkapacitet/Enskiltnummer?&__rp_/pts.SearchNumber_ndc=696&__rp_/pts.SearchNumber_operator=xxno_operatorxx&__rp_/pts.SearchNumber_telnumber=1788300

Categories

Resources