package org.glassfish.grizzly.http.util;
import java.io.CharConversionException;
import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.utils.Charsets;
public class HttpUtils {
private static final float[] MULTIPLIERS = new float[] { .1f, .01f, .001f };
public static String composeContentType(final String contentType, final String characterEncoding) {
if (characterEncoding == null) {
return contentType;
}
boolean hasCharset = false;
int semicolonIndex = -1;
int index = contentType.indexOf(';');
while (index != -1) {
int len = contentType.length();
semicolonIndex = index;
index++;
while (index < len && contentType.charAt(index) == ' ') {
index++;
}
if (index + 8 < len && contentType.charAt(index) == 'c' && contentType.charAt(index + 1) == 'h' && contentType.charAt(index + 2) == 'a'
&& contentType.charAt(index + 3) == 'r' && contentType.charAt(index + 4) == 's' && contentType.charAt(index + 5) == 'e'
&& contentType.charAt(index + 6) == 't' && contentType.charAt(index + 7) == '=') {
hasCharset = true;
break;
}
index = contentType.indexOf(';', index);
}
String newContentType;
if (hasCharset) {
newContentType = contentType.substring(0, semicolonIndex);
String tail = contentType.substring(index + 8);
int nextParam = tail.indexOf(';');
if (nextParam != -1) {
newContentType += tail.substring(nextParam);
}
} else {
newContentType = contentType;
}
final StringBuilder sb = new StringBuilder(newContentType.length() + characterEncoding.length() + 9);
return sb.append(newContentType).append(";charset=").append(characterEncoding).toString();
}
public static float convertQValueToFloat(final DataChunk dc, final int startIdx, final int stopIdx) {
float qvalue = 0f;
DataChunk.Type type = dc.getType();
try {
switch (type) {
case String: {
qvalue = HttpUtils.convertQValueToFloat(dc.toString(), startIdx, stopIdx);
break;
}
case Buffer: {
final BufferChunk bc = dc.getBufferChunk();
final int offs = bc.getStart();
qvalue = HttpUtils.convertQValueToFloat(bc.getBuffer(), offs + startIdx, offs + stopIdx);
break;
}
case Chars: {
final CharChunk cc = dc.getCharChunk();
final int offs = cc.getStart();
qvalue = HttpUtils.convertQValueToFloat(cc.getChars(), offs + startIdx, offs + stopIdx);
}
}
} catch (Exception e) {
qvalue = 0f;
}
return qvalue;
}
public static float convertQValueToFloat(final Buffer buffer, final int startIdx, final int stopIdx) {
float result = 0.0f;
boolean firstDigitProcessed = false;
int multIdx = -1;
for (int i = 0, len = stopIdx - startIdx; i < len; i++) {
final char c = (char) buffer.get(i + startIdx);
if (multIdx == -1) {
if (firstDigitProcessed && c != '.') {
throw new IllegalArgumentException(
"Invalid qvalue, " + buffer.toStringContent(Constants.DEFAULT_HTTP_CHARSET, startIdx, stopIdx) + ", detected");
}
if (c == '.') {
multIdx = 0;
continue;
}
}
if (Character.isDigit(c)) {
if (multIdx == -1) {
result += Character.digit(c, 10);
firstDigitProcessed = true;
if (result > 1) {
throw new IllegalArgumentException(
"Invalid qvalue, " + buffer.toStringContent(Constants.DEFAULT_HTTP_CHARSET, startIdx, stopIdx) + ", detected");
}
} else {
if (multIdx >= MULTIPLIERS.length) {
throw new IllegalArgumentException(
"Invalid qvalue, " + buffer.toStringContent(Constants.DEFAULT_HTTP_CHARSET, startIdx, stopIdx) + ", detected");
}
result += Character.digit(c, 10) * MULTIPLIERS[multIdx++];
}
} else {
throw new IllegalArgumentException(
"Invalid qvalue, " + buffer.toStringContent(Constants.DEFAULT_HTTP_CHARSET, startIdx, stopIdx) + ", detected");
}
}
return result;
}
public static float convertQValueToFloat(final String string, final int startIdx, final int stopIdx) {
float result = 0.0f;
boolean firstDigitProcessed = false;
int multIdx = -1;
for (int i = 0, len = stopIdx - startIdx; i < len; i++) {
final char c = string.charAt(i + startIdx);
if (multIdx == -1) {
if (firstDigitProcessed && c != '.') {
throw new IllegalArgumentException("Invalid qvalue, " + new String(string.toCharArray(), startIdx, stopIdx) + ", detected");
}
if (c == '.') {
multIdx = 0;
continue;
}
}
if (Character.isDigit(c)) {
if (multIdx == -1) {
result += Character.digit(c, 10);
firstDigitProcessed = true;
if (result > 1) {
throw new IllegalArgumentException("Invalid qvalue, " + new String(string.toCharArray(), startIdx, stopIdx) + ", detected");
}
} else {
if (multIdx >= MULTIPLIERS.length) {
throw new IllegalArgumentException("Invalid qvalue, " + new String(string.toCharArray(), startIdx, stopIdx) + ", detected");
}
result += Character.digit(c, 10) * MULTIPLIERS[multIdx++];
}
} else {
throw new IllegalArgumentException("Invalid qvalue, " + new String(string.toCharArray(), startIdx, stopIdx) + ", detected");
}
}
return result;
}
public static float convertQValueToFloat(final char[] chars, final int startIdx, final int stopIdx) {
float result = 0.0f;
boolean firstDigitProcessed = false;
int multIdx = -1;
for (int i = 0, len = stopIdx - startIdx; i < len; i++) {
final char c = chars[i + startIdx];
if (multIdx == -1) {
if (firstDigitProcessed && c != '.') {
throw new IllegalArgumentException("Invalid qvalue, " + new String(chars, startIdx, stopIdx) + ", detected");
}
if (c == '.') {
multIdx = 0;
continue;
}
}
if (Character.isDigit(c)) {
if (multIdx == -1) {
result += Character.digit(c, 10);
firstDigitProcessed = true;
if (result > 1) {
throw new IllegalArgumentException("Invalid qvalue, " + new String(chars, startIdx, stopIdx) + ", detected");
}
} else {
if (multIdx >= MULTIPLIERS.length) {
throw new IllegalArgumentException("Invalid qvalue, " + new String(chars, startIdx, stopIdx) + ", detected");
}
result += Character.digit(c, 10) * MULTIPLIERS[multIdx++];
}
} else {
throw new IllegalArgumentException("Invalid qvalue, " + new String(chars, startIdx, stopIdx) + ", detected");
}
}
return result;
}
public static int longToBuffer(long value, final byte[] buffer) {
int i = buffer.length;
if (value == 0) {
buffer[--i] = (byte) '0';
return i;
}
final int radix = 10;
final boolean negative;
if (value < 0) {
negative = true;
value = -value;
} else {
negative = false;
}
do {
final int ch = '0' + (int) (value % radix);
buffer[--i] = (byte) ch;
} while ((value /= radix) != 0);
if (negative) {
buffer[--i] = (byte) '-';
}
return i;
}
public static void longToBuffer(long value, final Buffer buffer) {
if (value == 0) {
buffer.put(0, (byte) '0');
buffer.limit(1);
return;
}
final int radix = 10;
final boolean negative;
if (value < 0) {
negative = true;
value = -value;
} else {
negative = false;
}
int position = buffer.limit();
do {
final int ch = '0' + (int) (value % radix);
buffer.put(--position, (byte) ch);
} while ((value /= radix) != 0);
if (negative) {
buffer.put(--position, (byte) '-');
}
buffer.position(position);
}
public static DataChunk filterNonPrintableCharacters(DataChunk message) {
if (message == null || message.isNull()) {
return null;
}
try {
message.toChars(Charsets.ASCII_CHARSET);
} catch (CharConversionException ignored) {
}
final CharChunk charChunk = message.getCharChunk();
final char[] content = charChunk.getChars();
final int start = charChunk.getStart();
final int end = charChunk.getEnd();
for (int i = start; i < end; i++) {
char c = content[i];
if (c <= 31 && c != 9 || c == 127 || c > 255) {
content[i] = ' ';
}
}
return message;
}
public static DataChunk filter(DataChunk message) {
if (message == null || message.isNull()) {
return null;
}
try {
message.toChars(Charsets.ASCII_CHARSET);
} catch (CharConversionException ignored) {
}
final CharChunk charChunk = message.getCharChunk();
final char[] content = charChunk.getChars();
StringBuilder result = null;
for (int i = charChunk.getStart(), end = charChunk.getEnd(); i < end; i++) {
switch (content[i]) {
case '<':
if (result == null) {
result = new StringBuilder(content.length + 50);
result.append(content, 0, i);
}
result.append("<");
break;
case '>':
if (result == null) {
result = new StringBuilder(content.length + 50);
result.append(content, 0, i);
}
result.append(">");
break;
case '&':
if (result == null) {
result = new StringBuilder(content.length + 50);
result.append(content, 0, i);
}
result.append("&");
break;
case '"':
if (result == null) {
result = new StringBuilder(content.length + 50);
result.append(content, 0, i);
}
result.append(""");
break;
default:
char c = content[i];
if (c <= 31 && c != 9 || c == 127 || c > 255) {
if (result == null) {
result = new StringBuilder(content.length + 50);
result.append(content, 0, i);
}
result.append("&#").append((int) c).append(';');
} else if (result != null) {
result.append(c);
}
}
}
if (result != null) {
final int len = result.length();
final char[] finalResult = new char[len];
result.getChars(0, len, finalResult, 0);
message.setChars(finalResult, 0, finalResult.length);
}
return message;
}
public static String filter(final String message) {
if (message == null) {
return null;
}
StringBuilder result = null;
final int len = message.length();
for (int i = 0; i < len; i++) {
final char c = message.charAt(i);
switch (c) {
case '<':
if (result == null) {
result = new StringBuilder(len + 50);
result.append(message, 0, i);
}
result.append("<");
break;
case '>':
if (result == null) {
result = new StringBuilder(len + 50);
result.append(message, 0, i);
}
result.append(">");
break;
case '&':
if (result == null) {
result = new StringBuilder(len + 50);
result.append(message, 0, i);
}
result.append("&");
break;
case '"':
if (result == null) {
result = new StringBuilder(len + 50);
result.append(message, 0, i);
}
result.append(""");
break;
default:
if (c <= 31 && c != 9 || c == 127 || c > 255) {
if (result == null) {
result = new StringBuilder(len + 50);
result.append(message, 0, i);
}
result.append("&#").append((int) c).append(';');
} else if (result != null) {
result.append(c);
}
}
}
return result == null ? message : result.toString();
}
}