diff --git a/core/.classpath b/core/.classpath
index 17a6103c14d..1867836084a 100644
--- a/core/.classpath
+++ b/core/.classpath
@@ -11,7 +11,6 @@
-
@@ -39,5 +38,6 @@
+
diff --git a/server/.classpath b/server/.classpath
index 8a0c5b39e0c..fe6302cf152 100644
--- a/server/.classpath
+++ b/server/.classpath
@@ -13,13 +13,13 @@
-
-
+
+
diff --git a/server/src/com/cloud/api/ApiGsonHelper.java b/server/src/com/cloud/api/ApiGsonHelper.java
index 9877d27bdba..4e11d4b1977 100644
--- a/server/src/com/cloud/api/ApiGsonHelper.java
+++ b/server/src/com/cloud/api/ApiGsonHelper.java
@@ -14,3 +14,4 @@ public class ApiGsonHelper {
return s_gBuilder;
}
}
+
diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java
index 7613b6db72a..0120fbf02c5 100755
--- a/server/src/com/cloud/api/ApiServer.java
+++ b/server/src/com/cloud/api/ApiServer.java
@@ -274,9 +274,9 @@ public class ApiServer implements HttpRequestHandler {
response.setStatusCode(se.getErrorCode());
response.setReasonPhrase(se.getDescription());
BasicHttpEntity body = new BasicHttpEntity();
- body.setContentType("text/xml; charset=UTF-8");
+ body.setContentType("text/xml");
String responseStr = ""+se.getErrorCode()+" : "+se.getDescription()+"";
- body.setContent(new ByteArrayInputStream(responseStr.getBytes()));
+ body.setContent(new ByteArrayInputStream(responseStr.getBytes("UTF-8")));
response.setEntity(body);
sb.append(" " + se.getErrorCode() + " " + responseStr.length());
@@ -714,19 +714,19 @@ public class ApiServer implements HttpRequestHandler {
BasicHttpEntity body = new BasicHttpEntity();
if (BaseCmd.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
// JSON response
- body.setContentType("text/javascript; charset=UTF-8");
+ body.setContentType("text/javascript");
if (responseText == null) {
- body.setContent(new ByteArrayInputStream("{ \"error\" : { \"description\" : \"Internal Server Error\" } }".getBytes()));
+ body.setContent(new ByteArrayInputStream("{ \"error\" : { \"description\" : \"Internal Server Error\" } }".getBytes("UTF-8")));
}
} else {
- body.setContentType("text/xml; charset=UTF-8");
+ body.setContentType("text/xml");
if (responseText == null) {
- body.setContent(new ByteArrayInputStream("Internal Server Error".getBytes()));
+ body.setContent(new ByteArrayInputStream("Internal Server Error".getBytes("UTF-8")));
}
}
if (responseText != null) {
- body.setContent(new ByteArrayInputStream(responseText.getBytes()));
+ body.setContent(new ByteArrayInputStream(responseText.getBytes("UTF-8")));
}
resp.setEntity(body);
} catch (Exception ex) {
diff --git a/server/src/com/cloud/api/ApiServlet.java b/server/src/com/cloud/api/ApiServlet.java
index 1e6e87eba11..0ba8243be90 100755
--- a/server/src/com/cloud/api/ApiServlet.java
+++ b/server/src/com/cloud/api/ApiServlet.java
@@ -320,14 +320,10 @@ public class ApiServlet extends HttpServlet {
} else {
resp.setContentType("text/xml");
}
- resp.setStatus(isError? HttpServletResponse.SC_INTERNAL_SERVER_ERROR : HttpServletResponse.SC_OK);
- byte[] respBytes = response.getBytes();
- resp.setContentLength(respBytes.length);
- OutputStream os = resp.getOutputStream();
- os.write(respBytes);
- os.flush();
- os.close();
- resp.flushBuffer();
+ resp.setStatus(isError? HttpServletResponse.SC_INTERNAL_SERVER_ERROR : HttpServletResponse.SC_OK);
+
+ // use getWriter() instead of manually manipulate encoding to have better localization support
+ resp.getWriter().print(response);
} catch (IOException ioex) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("exception writing response: " + ioex);
diff --git a/server/src/com/cloud/api/response/ApiResponseSerializer.java b/server/src/com/cloud/api/response/ApiResponseSerializer.java
index ca1852eaaf6..85e60baa3d6 100644
--- a/server/src/com/cloud/api/response/ApiResponseSerializer.java
+++ b/server/src/com/cloud/api/response/ApiResponseSerializer.java
@@ -4,10 +4,10 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
import java.util.Date;
-import java.util.LinkedList;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.apache.log4j.Logger;
@@ -28,6 +28,16 @@ public class ApiResponseSerializer {
return toXMLSerializedString(result);
}
}
+
+ private static final Pattern s_unicodeEscapePattern = Pattern.compile("\\\\u([0-9A-Fa-f]{4})");
+ public static String unescape(String escaped) {
+ String str = escaped;
+ Matcher matcher = s_unicodeEscapePattern.matcher(str);
+ while(matcher.find()) {
+ str = str.replaceAll("\\" + matcher.group(0), Character.toString((char)Integer.parseInt(matcher.group(1), 16)));
+ }
+ return str;
+ }
private static String toJSONSerializedString(ResponseObject result) {
if (result != null) {
@@ -39,10 +49,12 @@ public class ApiResponseSerializer {
List extends ResponseObject> responses = ((ListResponse)result).getResponses();
if ((responses != null) && !responses.isEmpty()) {
int count = responses.size();
- String jsonStr = gson.toJson(responses.get(0));
+ String jsonStr = gson.toJson(responses.get(0));;
+ jsonStr = unescape(jsonStr);
sb.append("{ \"" + responses.get(0).getObjectName() + "\" : [ " + jsonStr);
for (int i = 1; i < count; i++) {
jsonStr = gson.toJson(responses.get(i));
+ jsonStr = unescape(jsonStr);
sb.append(", " + jsonStr);
}
sb.append(" ] }");
@@ -54,6 +66,7 @@ public class ApiResponseSerializer {
} else {
String jsonStr = gson.toJson(result);
if ((jsonStr != null) && !"".equals(jsonStr)) {
+ jsonStr = unescape(jsonStr);
if (result instanceof AsyncJobResponse || result instanceof CreateCmdResponse) {
sb.append(jsonStr);
} else {
diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java
index b43bae7fdb7..7876a343a2b 100644
--- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java
+++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java
@@ -66,15 +66,16 @@ public class ConsoleProxyServlet extends HttpServlet {
}
@Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
+
try {
String userId = null;
String account = null;
Account accountObj = null;
-
+
Map params = new HashMap();
params.putAll(req.getParameterMap());
-
+
HttpSession session = req.getSession(false);
if(session == null) {
if(verifyRequest(params)) {
diff --git a/ui/scripts/cloud.core.js b/ui/scripts/cloud.core.js
index fff1902cc93..aa0637821d1 100644
--- a/ui/scripts/cloud.core.js
+++ b/ui/scripts/cloud.core.js
@@ -537,11 +537,11 @@ function createURL(url) {
}
function fromdb(val) {
- return sanitizeXSS(unescape(noNull(val)));
+ return sanitizeXSS(noNull(val));
}
function todb(val) {
- return encodeURIComponent(escape(val));
+ return encodeURIComponent(val);
}
var midmenuItemCount = 20;
diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java
index dfa6d72c78a..a5dab05daa9 100755
--- a/utils/src/com/cloud/utils/db/GenericDaoBase.java
+++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java
@@ -18,6 +18,7 @@
package com.cloud.utils.db;
import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@@ -448,7 +449,20 @@ public abstract class GenericDaoBase implements Gene
try {
final Class> type = field.getType();
if (type == String.class) {
- field.set(entity, rs.getString(index));
+ byte[] bytes = rs.getBytes(index);
+ if(bytes != null) {
+ try {
+ field.set(entity, new String(bytes, "UTF-8"));
+ } catch (IllegalArgumentException e) {
+ assert(false);
+ throw new CloudRuntimeException("IllegalArgumentException when converting UTF-8 data");
+ } catch (UnsupportedEncodingException e) {
+ assert(false);
+ throw new CloudRuntimeException("UnsupportedEncodingException when converting UTF-8 data");
+ }
+ } else {
+ field.set(entity, null);
+ }
} else if (type == long.class) {
field.setLong(entity, rs.getLong(index));
} else if (type == Long.class) {
@@ -560,7 +574,16 @@ public abstract class GenericDaoBase implements Gene
@DB(txn=false) @SuppressWarnings("unchecked")
protected M getObject(Class type, ResultSet rs, int index) throws SQLException {
if (type == String.class) {
- return (M)rs.getString(index);
+ byte[] bytes = rs.getBytes(index);
+ if(bytes != null) {
+ try {
+ return (M)new String(bytes, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new CloudRuntimeException("UnsupportedEncodingException exception while converting UTF-8 data");
+ }
+ } else {
+ return (M)null;
+ }
} else if (type == int.class) {
return (M)new Integer(rs.getInt(index));
} else if (type == Integer.class) {
@@ -1197,10 +1220,23 @@ public abstract class GenericDaoBase implements Gene
final Column column = attr.field.getAnnotation(Column.class);
final int length = column != null ? column.length() : 255;
+ // to support generic localization, utilize MySql UTF-8 support
if (length < str.length()) {
- pstmt.setString(j, str.substring(0, column.length()));
+ try {
+ pstmt.setBytes(j, str.substring(0, column.length()).getBytes("UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ // no-way it can't support UTF-8 encoding
+ assert(false);
+ throw new CloudRuntimeException("UnsupportedEncodingException when saving string as UTF-8 data");
+ }
} else {
- pstmt.setString(j, str);
+ try {
+ pstmt.setBytes(j, str.getBytes("UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ // no-way it can't support UTF-8 encoding
+ assert(false);
+ throw new CloudRuntimeException("UnsupportedEncodingException when saving string as UTF-8 data");
+ }
}
} else if (attr.field.getType() == Date.class) {
final Date date = (Date)value;