We recently ran into a situation where a client submitted a ridiculous files name (it was over 95 characters and full of spaces). edtftp threw an ArrayIndexOutOfBounds error that I traced to the split method. I then see that there is a MAX_FIELDS constant that was set to 20. It seemed to be an arbitrary number as the returned array only included the actual number of elements found. I know nobody thought it would every go over that, but you just never can guess what some folks are going to do. Anyway, I modified the method to build the elements in an ArrayList and then convert that to an array to return the result. I then deleted the MAX_FIELDS variable just to reduce confusion and the local pos variable is no longer needed. This has the benefit of handling an arbitrary number of elements with no fixed limitation. I don't think there will be a noticable performance hit in this case since the string references are being created anyway and, if I remember correctly, the ArrayList's internal array will be big enough for 99.9% of files that need to be parsed so it will not need to be resized. I know method calls are slower, but sometimes they make sense. Anyway, here is the code I recompiled into edt ftp for our use. Unless there is an objection, I would think this might be a helpful modification to include in future version of the library:
/**
* Splits string consisting of fields separated by
* whitespace into an array of strings. Yes, we could
* use String.split() but this would restrict us to 1.4+
*
* @param str string to split
* @return array of fields
*/
protected String[] split(String str) {
ArrayList fields = new ArrayList();
StringBuffer field = new StringBuffer();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (!Character.isWhitespace(ch))
field.append(ch);
else {
if (field.length()> 0) {
fields.add(field.toString());
field.setLength(0);
}
}
}
// pick up last field
if (field.length() > 0) {
fields.add(field.toString());
}
String[] result = new String[fields.size()];
System.arraycopy(fields.toArray(), 0, result, 0, result.length);
return result;
}