Why would this cause a StringIndexOutOfBoundsException? Android - java

I am working on a small file manager to help me learn the basics of android, but I keep running into an error. WHenever I have a lot of items in the folder, it crashes and I get a message similar to this one,
java.lang.StringIndexOutOfBoundsException: length=26; regionStart=23; regionLength=-2
What could be causing this? The line it points to is line 2:
1.)String mimeType = "";
2.)mimeType = URLConnection.guessContentTypeFromName(f.getName());

You are missing some key lines we need to see, such as where f (a File? a URI?) is defined. However when I have seen this problem before it was caused by a URI with no Protocol set.
Making sure you have an extension and using MimeTypeMap#getMimeTypeFromExtension() is probably a good bet too

This error happens to me when the URL has a fragment, which can be identified by a # followed by some value. (For more on URL fragments, see https://www.w3.org/Addressing/URL/4_2_Fragments.html)
The URL fragment is not helpful in guessing content type, and since it is problematic in this case, it should be removed before calling URLConnection.guessContentTypeFromName().
Here is a simple function that returns a URL without the fragment:
private fun getSafeUrlForGuessing(url: String): String {
return try {
val uri = Uri.parse(url)
if (uri.scheme?.startsWith("http") == true) {
uri.buildUpon()
.fragment(null) // URLs with fragments cause URLConnection.guessContentTypeFromName() to throw
.build()
.toString()
} else {
url
}
} catch (error: Throwable) {
url
}
}

Related

GeoFireStore getLocation returns null

I tried to use GeoFireStore to set,get and query location.
I tried first to setLocation by using:
geoFirestoreRef = FirebaseFirestore.getInstance().collection("Locations");
geoFirestore = new GeoFirestore(geoFirestoreRef);
geoFirestore.setLocation( auth.getUid(), new GeoPoint(Lat_Coordinate,Lon_Coordinate) );
It all worked good and created the following in my database:
Now, I tried to getLocation to see if it is working by using:
geoFirestore.getLocation( auth.getUid(), new GeoFirestore.LocationCallback() {
#Override
public void onComplete(GeoPoint geoPoint, Exception e) {
Log.d("ERROR", "Error getting documents: " + e);
}
} );
and for some reason, it can't get anything eventho that I can see this location in my database.
I get the exception: java.lang.NullPointerException: Location doesn't exist.
Any ideas please?
Thank you
I had this issue with the library too. When looking into the source, I saw a little mistake here.
So I made a pull request with the fix. You can either use the fork link or clone the repository and fix line 192 with :
if (geoPoint != null)

How to build a short Dynamic Link with a Desktop Fallback URL on Android?

I have implemented deep link in my Android App to share content. The problem is on Android I can't find a way to set a Fallback URL when the user open the short link on his desktop.
With the Firebase DynamicLink.Builder I can set iOS fallback URL because my app doesn't exist on iOS but I can't find a way to set the dfl parameters in my link.
Which lead the user to an error page like this :
Here how I build my short dynamic link:
//link example : https://app.example.com/details/ebLvAV9fi9S7Pab0qR3a
String link = domainUri + "/details/" + object.getUid();
FirebaseDynamicLinks.getInstance().createDynamicLink()
.setLink(Uri.parse(link))
.setDomainUriPrefix(domainUri)
.setAndroidParameters(new DynamicLink.AndroidParameters.Builder().setMinimumVersion(1).build())
// Fallback Url for iOS
.setIosParameters(new DynamicLink.IosParameters.Builder("").setFallbackUrl(Uri.parse(RMP_WEB_BASE_URL)).build())
.setSocialMetaTagParameters(
new DynamicLink.SocialMetaTagParameters.Builder()
.setTitle(title)
.setDescription(description)
.setImageUrl(Uri.parse(imageUrl))
.build())
.buildShortDynamicLink()
.addOnCompleteListener(new OnCompleteListener<ShortDynamicLink>() {
#Override
public void onComplete(#NonNull Task<ShortDynamicLink> task) {
if (task.isSuccessful() && task.getResult() != null) {
shortLink = task.getResult().getShortLink();
//Create Shareable Intent
//...
}
}
});
I have read that I need to specify a Desktop Fallback URL like the iOS one but DynamicLink.Builder doesn't seems to include one.
I would like to redirect my user to the home page https://example.com when they open the link from a non-android device.
I have tried to use setLongLink(longLink) in the DynamicLink.Builder with the parameters ?dfl=https://example.com but it doesn't seems to work and it even break my dynamic link on android.
This is a Swift solution but may be helpful to others-
Unfortunately, there is currently no built-in method to handle this programmatically through the Firebase url editor. You must manually add an 'ofl' parameter to the link. The easiest way to do this:
// Grab link from Firebase builder
guard var longDynamicLink = shareLink.url else { return }
// Parse URL to string
var urlStr = longDynamicLink.absoluteString
// Append the ofl fallback (ofl param specifies a device other than ios or android)
urlStr = urlStr + "&ofl=https://www.google.com/"
// Convert back to a URL
var urlFinal = URL(string: urlStr)!
// Shorten the url & check for errors
DynamicLinkComponents.shortenURL(urlFinal, options: nil, completion:{ [weak self] url,warnings,error in
if let _ = error{
return
}
if let warnings = warnings{
for warning in warnings{
print("Shorten URL warnings: ", warning)
}
}
guard let shortUrl = url else {return}
// prompt the user with UIActivityViewController
self?.showShareSheet(url: shortUrl)
})
The final URL can then be used to present the shareable panel with another function like:
self.showShareSheet(url: finalUrl) which triggers the UIActivityViewController
Credit to http://ostack.cn/?qa=168161/ for the original idea
More about ofl: https://firebase.google.com/docs/dynamic-links/create-manually?authuser=3#general-params

CSS validation with AntiSamy

I have a String, and I want to validate whether it is a valid CSS value or not. In the documentation of AntiSamy, I found that I might be able to use CSSValidator.isValidProperty (http://javadox.com/org.owasp/antisamy/1.4/org/owasp/validator/css/CssValidator) to do so. However, the type of the second param requires LexicalUnit.
Is there another way to validate a String with AnitSamy?
I think what you want is the CssScanner.
/****** pull out style tag from html *****/
Pattern p = Pattern.compile("<style>([\\s\\S]+?)</style>");
Matcher m = p.matcher(validHTML);
// if we find a match, get the group
if (m.find()) {
// get the matching group
codeGroup = m.group(1);
}
/****** block for checking all css for validity *****/
InternalPolicy policy = null;
try {
policy = (InternalPolicy) InternalPolicy.getInstance("antisamy-ebay.xml");
} catch (PolicyException e) {
e.printStackTrace();
}
ResourceBundle messages = ResourceBundle.getBundle("AntiSamy", Locale.getDefault());
CssScanner scanner = new CssScanner(policy, messages);
CleanResults results = scanner.scanStyleSheet(codeGroup, Integer.MAX_VALUE);
validCSS = results.getCleanHTML().toString();
That is the part of the code that worked for me. Let me know if any of this does not work for you, I have variables declared at the top of the code because I am also handling html validation in here too. So some variables are not in this code. But it should point you in the right direction. Also, you need a policy in place, I chose the ebay policy, this guides the whitelist of what the css will allow for the resulting output. I have not used the CssValidator, so I am not sure how they compare, but CssScanner does a great job of giving back clean css.

How to fix the HTTP Response splitting vulnerability with ESAPI

after a recent findbugs (FB) run it complains about a: Security - HTTP Response splitting vulnerability The following code triggers it:
String referrer = req.getParameter("referrer");
if (referrer != null) {
launchURL += "&referrer="+(referrer);
}
resp.sendRedirect(launchURL);
Basically the 'referrer' http parameter contains an url, to which, when clicking on a back button in our application the browser returns to. It is appended to the url as a parameter. After a bit research i know that i need to sanitize the referrer url. After a bit more research i found the esapi project which seem to offer this kind of functionality:
//1st canonicalize
import org.owasp.esapi.Encoder;
import org.owasp.esapi.Validator;
import org.owasp.esapi.reference.DefaultEncoder;
import org.owasp.esapi.reference.DefaultValidator;
[...]
Encoder encoder = new DefaultEncoder(new ArrayList<String>());
String cReferrer = encoder.canonicalize(referrer);
However I didn't figure out how to detect e.g. jscript code or other stuff which doesn't belong to a referrer url. So how can I achieve that with esapi?
I tried:
Validator validator = new DefaultValidator(encoder);
validator.isValidInput("Redirect URL",referrer,"HTTPParameterValue",512,false);
however this doesn't work. What I need is a function which results in:
http://www.google.com (ok)
http://www.google.com/login?dest=http://google.com/%0D%0ALocation: javascript:%0D%0A%0D%0Aalert(document.cookie) (not ok)
Or is it enough to call the following statement?
encoder.encodeForHTMLAttribute(referrer);
Any help appreciated.
Here's my final solution if anyone is interested. First I canonicalize and then URL decode the string. If a CR or LF exists (\n \r) I just cut of the rest of that potential 'attack' string starting with \n or \r.
String sanitize(String url) throws EncodingException{
Encoder encoder = new DefaultEncoder(new ArrayList<String>());
//first canonicalize
String clean = encoder.canonicalize(url).trim();
//then url decode
clean = encoder.decodeFromURL(clean);
//detect and remove any existent \r\n == %0D%0A == CRLF to prevent HTTP Response Splitting
int idxR = clean.indexOf('\r');
int idxN = clean.indexOf('\n');
if(idxN >= 0 || idxR>=0){
if(idxN<idxR){
//just cut off the part after the LF
clean = clean.substring(0,idxN);
}
else{
//just cut off the part after the CR
clean = clean.substring(0,idxR);
}
}
//re-encode again
return encoder.encodeForURL(clean);
}
Theoretically i could have later verified the value against 'HTTPParameterValue' regex which is defined in the ESAPI.properties however it didn't like colon in the http:// and I didn't investigated further.
And one more remark after testing it: Most modern browser nowadays (Firefox > 3.6, Chrome, IE10 etc.) detect this kind of vulnerability and do not execute the code...
I think you have the right idea, but are using an inappropriate encoder. The Referer [sic] header value is really a URL, not an HTML attribute, so you really want to use:
encoder.encodeForURL(referrer);
-kevin
I would suggest white-listing approach wherein you check the referrer string only for permissible characters. Regex would be a good option.
EDIT:
The class org.owasp.esapi.reference.DefaultEncoder being used by you is not really encoding anything. Look at the source code of the method encodeForHTMLAttribute(referrer) here at grepcode. A typical URL encoding (encoding carriage return and line feed) too wont help.
So the way forward would be device some validation logic which checks for valid set of characters. Here is another insightful article.
The accepted answer will not work if in case there is "\n\r" in the string.
Example:
If I have string: "This is str\n\rstr", it returns "This is str\nstr"
Rectified version of above accepted answer is:
String sanitizeCarriageReturns(String value) {
int idxR = value.indexOf('\r');
int idxN = value.indexOf('\n');
if (idxN >= 0 || idxR >= 0) {
if ((idxN > idxR && idxR<0) || (idxR > idxN && idxR>=0)) {
value = value.substring(0, idxN);
} else if (idxN < idxR){
value = value.substring(0, idxR);
}
}
return value;
}

Best practice: catching failure points in java.net.URL

New to the JVM, working with Scala and Play 2.0
I'm converting a legacy application over to Play, one that requires payment processing via Authorize.net. Looking through java.net.URL source, there are numerous potential points of failure. Given the interface I've written below, where would you implement try/catch blocks? I'll need to adapt method signatures accordingly, probably returning an Either[Error, Success] to calling client code
import java.net.{URL, URLEncoder}
import java.io.{BufferedReader, DataOutputStream, InputStreamReader}
import javax.net.ssl._
trait Authnet {
private val prodUrl = "https://secure.authorize.net/gateway/transact.dll"
private val testUrl = "https://test.authorize.net/gateway/transact.dll"
protected def authNetProcess(params: Map[String,String]) = {
val(conn, urlParams) = connect(params)
val request = new DataOutputStream( conn.getOutputStream )
request.write(urlParams.getBytes)
request.flush()
request.close()
val response = new BufferedReader(new InputStreamReader(conn.getInputStream))
val results = response.readLine().split("\\|")
response.close()
results.toList
}
private def connect(params: Map[String,String]) = {
val urlParams = (config ++ params) map { case(k,v) =>
URLEncoder.encode(k, "UTF-8") + "=" + URLEncoder.encode(v, "UTF-8")
} mkString("&")
lazy val url = if (isDev) new URL(testUrl) else new URL(prodUrl)
val conn = url.openConnection
conn.setDoOutput(true)
conn.setUseCaches(false)
(conn, urlParams)
}
private val config = Map(
'x_login -> "...",
'x_tran_key -> "...",
...
)
}
Stick to the thumb rule:
Only catch an exception if you must handle it.
There is no sharp definition for "must handle" but it means you should resist the urge to catch an exception because you can just to throw a different exception.
The "must handle" is mainly defined by how your application should work or other dependencies.
If the application requires to display an error to the user instead of aborting with an exception, then it's a must.
In that case catching the excpetion adds also some meaningful processing.
If an API requires to throw a different exception, then it's a must, but the APIs definition is possibly not sound.
I am always questioning the added value of replacing an exception with just another exception.
Applying this to your example:
Would it add some value to catch an exception from connect() in authNetProcess()?
No! There is no way to handle that exception inside of connect(). So its ok to leave that exception to the caller of authNetProcess. There you could provide different handling based on the kind of the exception.
EDIT
Well, if any part of the connection/stream process fails, the transaction is hosed, so silly to only capture error on opening of the connection. I'm just wrapping the whole transaction in a catching (operation) option block, and leaving it at that; I'm not too concerned re: the exact cause of the error (whatever it is gets logged) as it is transient, so catch it, have the user try again; if error persists, contact us...
ORIGINAL
OK, well, given the up votes and lack of commentary to-date, the only conclusion I can draw is...nobody around here knows what they're doing! heh, heh, joking ;-)
Although I'm new to the JVM, try/catch/finally bloat is getting old fast; via the wonders of Scala type inference, I have abstracted away general error handling into concise implementations:
catching ( operation ) option
catching ( operation ) either
Unless I receive feedback otherwise, for now I'm copping out by just catching connection creation (I believe, in this case, the most likely error condition). Here's the new implementation:
protected def authNetProcess(params: Map[String,String]) = {
connect() match {
case Some(conn) =>
val request = new DataOutputStream(conn.getOutputStream)
request.write(getUrlParams(params).getBytes)
request.flush()
request.close()
val response = new BufferedReader(new InputStreamReader(conn.getInputStream))
val results = response.readLine().split("\\|")
response.close()
results.toList
case None => List[String]()
}
}
private def connect() = {
lazy val url = if (isDev) new URL(testUrl) else new URL(prodUrl)
catching ( url.openConnection ) option match {
case Some(conn) =>
conn.setDoOutput(true)
conn.setUseCaches(false)
//conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
Some(conn)
case None => None // connection failed
}
}
I suppose a more rigorous approach would be to extract all potential error conditions into maybeWorked Option operations, and then wrap them all up in a for comprehension. That's probably the proper/responsible approach...but only so many hours in a day, will revisit this later
feedback appreciated!

Categories