Working on improving URL handling.
This commit is contained in:
parent
594ebeda22
commit
2de267af6b
1 changed files with 111 additions and 9 deletions
|
@ -20,6 +20,8 @@ import org.apache.commons.logging.LogFactory;
|
||||||
* Brian Caruso with changes contributed by David Cliff, 2010-11-03
|
* Brian Caruso with changes contributed by David Cliff, 2010-11-03
|
||||||
* Before 2010-11 this was a private class of URLRewritingHttpServletResponse.java.
|
* Before 2010-11 this was a private class of URLRewritingHttpServletResponse.java.
|
||||||
*
|
*
|
||||||
|
* Useful reference:
|
||||||
|
* http://labs.apache.org/webarch/uri/rfc/rfc3986.html
|
||||||
*/
|
*/
|
||||||
class VitroURL {
|
class VitroURL {
|
||||||
// this is to get away from some of the
|
// this is to get away from some of the
|
||||||
|
@ -35,10 +37,17 @@ class VitroURL {
|
||||||
public List<String[]> queryParams;
|
public List<String[]> queryParams;
|
||||||
public String fragment;
|
public String fragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pattern to get the path and query of a relative URL
|
||||||
|
* ex.
|
||||||
|
* /entity -> /entity
|
||||||
|
* /entity?query=abc -> /entity query=abc
|
||||||
|
*/
|
||||||
|
private Pattern pathPattern = Pattern.compile("([^\\?]*)\\??(.*)");
|
||||||
|
|
||||||
private Pattern commaPattern = Pattern.compile("/");
|
private Pattern commaPattern = Pattern.compile("/");
|
||||||
private Pattern equalsSignPattern = Pattern.compile("=");
|
private Pattern equalsSignPattern = Pattern.compile("=");
|
||||||
private Pattern ampersandPattern = Pattern.compile("&");
|
private Pattern ampersandPattern = Pattern.compile("&");
|
||||||
private Pattern questionMarkPattern = Pattern.compile("\\?");
|
|
||||||
public boolean pathBeginsWithSlash = false;
|
public boolean pathBeginsWithSlash = false;
|
||||||
public boolean pathEndsInSlash = false;
|
public boolean pathEndsInSlash = false;
|
||||||
public boolean wasXMLEscaped = false;
|
public boolean wasXMLEscaped = false;
|
||||||
|
@ -65,9 +74,18 @@ class VitroURL {
|
||||||
// Under normal circumstances, this is because the urlStr is relative
|
// Under normal circumstances, this is because the urlStr is relative
|
||||||
// We'll assume that we just have a path and possibly a query string.
|
// We'll assume that we just have a path and possibly a query string.
|
||||||
// This is likely to be a bad assumption, but let's roll with it.
|
// This is likely to be a bad assumption, but let's roll with it.
|
||||||
String[] urlParts = questionMarkPattern.split(urlStr);
|
Matcher m = pathPattern.matcher(urlStr);
|
||||||
|
String[] urlParts = new String[2];
|
||||||
|
if( m.matches() ){
|
||||||
|
urlParts[0]= m.group(1);
|
||||||
|
if( m.groupCount() == 2 )
|
||||||
|
urlParts[1] = m.group(2);
|
||||||
|
}else{
|
||||||
|
//???
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.pathParts = splitPath(URLDecoder.decode(urlParts[0],characterEncoding));
|
this.pathParts = splitPath(URLDecoder.decode(getPath(urlStr),characterEncoding));
|
||||||
this.pathBeginsWithSlash = beginsWithSlash(urlParts[0]);
|
this.pathBeginsWithSlash = beginsWithSlash(urlParts[0]);
|
||||||
this.pathEndsInSlash = endsInSlash(urlParts[0]);
|
this.pathEndsInSlash = endsInSlash(urlParts[0]);
|
||||||
if (urlParts.length>1) {
|
if (urlParts.length>1) {
|
||||||
|
@ -79,6 +97,15 @@ class VitroURL {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getPath(String urlStr){
|
||||||
|
Matcher m = pathPattern.matcher(urlStr);
|
||||||
|
if( m.matches() )
|
||||||
|
return m.group(1);
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<String> splitPath(String pathStr) {
|
private List<String> splitPath(String pathStr) {
|
||||||
String[] splitStr = commaPattern.split(pathStr);
|
String[] splitStr = commaPattern.split(pathStr);
|
||||||
if (splitStr.length>0) {
|
if (splitStr.length>0) {
|
||||||
|
@ -123,19 +150,94 @@ class VitroURL {
|
||||||
return (pathStr.charAt(pathStr.length()-1) == '/');
|
return (pathStr.charAt(pathStr.length()-1) == '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String[]> parseQueryParams(String queryStr) {
|
|
||||||
|
/**
|
||||||
|
* This is attempting to parse query parameters that might not be URLEncoded.
|
||||||
|
* This seems like a huge problem. We will only correctly handle odd things
|
||||||
|
* as a query parameter 'uri' in the last position.
|
||||||
|
*
|
||||||
|
* @param queryStr
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected List<String[]> parseQueryParams(String queryStr) {
|
||||||
List<String[]> queryParamList = new ArrayList<String[]>();
|
List<String[]> queryParamList = new ArrayList<String[]>();
|
||||||
if (queryStr == null) {
|
if (queryStr == null) {
|
||||||
return queryParamList;
|
return queryParamList;
|
||||||
}
|
}
|
||||||
String[] keyValuePairs = ampersandPattern.split(queryStr);
|
|
||||||
for (int i=0; i<keyValuePairs.length; i++) {
|
while ( queryStr.length() > 0 ){
|
||||||
String[] pairParts = equalsSignPattern.split(keyValuePairs[i]);
|
//remove leading & if there was one
|
||||||
queryParamList.add(pairParts);
|
if( queryStr.startsWith("&"))
|
||||||
|
queryStr = queryStr.substring(1);
|
||||||
|
|
||||||
|
String[] simplepair = getSimpleQueryMatch(queryStr);
|
||||||
|
if( simplepair != null ){
|
||||||
|
if( simplepair[1].contains("?") ){
|
||||||
|
//must be odd final pair
|
||||||
|
String[] finalPair = getFinalPairQueryMatch(queryStr);
|
||||||
|
if( finalPair != null){
|
||||||
|
queryParamList.add(finalPair);
|
||||||
|
queryStr="";
|
||||||
|
}else{
|
||||||
|
throw new Error("Cannot parse query string for URL " +
|
||||||
|
"queryParams: \"" + queryStr + "\" this only accepts " +
|
||||||
|
"complex parameters in the final position with the key 'uri'.");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
queryParamList.add(simplepair);
|
||||||
|
// remove found simple key vaule pair from query str
|
||||||
|
queryStr = queryStr.substring(
|
||||||
|
simplepair[0].length()+simplepair[1].length()+1);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//maybe there is an odd final pair
|
||||||
|
String[] finalPair = getFinalPairQueryMatch(queryStr);
|
||||||
|
if( finalPair != null){
|
||||||
|
queryParamList.add(finalPair);
|
||||||
|
queryStr="";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return queryParamList;
|
return queryParamList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Query for simple query param at start of string. */
|
||||||
|
private Pattern simpleQueryParamPattern = Pattern.compile("^([^\\=]*)=([^\\&]*)");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for a simple match in a queryParam.
|
||||||
|
* May return null.
|
||||||
|
*/
|
||||||
|
protected String[] getSimpleQueryMatch(String querystr){
|
||||||
|
Matcher simpleMatch = simpleQueryParamPattern.matcher(querystr);
|
||||||
|
if( simpleMatch.find() ){
|
||||||
|
String[] rv = new String[2];
|
||||||
|
rv[0]=simpleMatch.group(1);
|
||||||
|
rv[1]=simpleMatch.group(2);
|
||||||
|
return rv;
|
||||||
|
}else{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Pattern finalQueryParamPattern = Pattern.compile("^(uri)=(.*)");
|
||||||
|
/**
|
||||||
|
* Checks only for uri=.* as the last match of the queryParams.
|
||||||
|
* May return null.
|
||||||
|
*/
|
||||||
|
protected String[] getFinalPairQueryMatch(String querystr){
|
||||||
|
Matcher finalMatch = finalQueryParamPattern.matcher(querystr);
|
||||||
|
if( finalMatch.find() ){
|
||||||
|
String[] rv = new String[2];
|
||||||
|
rv[0]=finalMatch.group(1);
|
||||||
|
rv[1]=finalMatch.group(2);
|
||||||
|
return rv;
|
||||||
|
}else{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer out = new StringBuffer();
|
StringBuffer out = new StringBuffer();
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue