/******************************************************************************* * Copyright 2013-2016 alladin-IT GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package at.alladin.rmbt.controlServer; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.text.MessageFormat; import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.Locale; import java.util.UUID; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.restlet.resource.Get; import org.restlet.resource.Post; import at.alladin.rmbt.db.Client; import at.alladin.rmbt.db.QoSTestTypeDesc; import at.alladin.rmbt.db.dao.QoSTestTypeDescDao; import at.alladin.rmbt.shared.Helperfunctions; import at.alladin.rmbt.shared.ResourceManager; import at.alladin.rmbt.shared.RevisionHelper; import com.google.common.base.Strings; public class SettingsResource extends ServerResource { /** * * @param entity * @return */ @Post("json") public String request(final String entity) { long startTime = System.currentTimeMillis(); addAllowOrigin(); JSONObject request = null; final ErrorList errorList = new ErrorList(); final JSONObject answer = new JSONObject(); String answerString; final String clientIpRaw = getIP(); System.out.println(MessageFormat.format(labels.getString("NEW_SETTINGS_REQUEST"), clientIpRaw)); if (entity != null && !entity.isEmpty()) // try parse the string to a JSON object try { request = new JSONObject(entity); String lang = request.optString("language"); // Load Language Files for Client final List<String> langs = Arrays.asList(settings.getString("RMBT_SUPPORTED_LANGUAGES").split(",\\s*")); if (langs.contains(lang)) { errorList.setLanguage(lang); labels = ResourceManager.getSysMsgBundle(new Locale(lang)); } else lang = settings.getString("RMBT_DEFAULT_LANGUAGE"); // System.out.println(request.toString(4)); if (conn != null) { final Client client = new Client(conn); int typeId = 0; if (request.optString("type").length() > 0) { typeId = client.getTypeId(request.getString("type")); if (client.hasError()) errorList.addError(client.getError()); } final List<String> clientNames = Arrays.asList(settings.getString("RMBT_CLIENT_NAME") .split(",\\s*")); final JSONArray settingsList = new JSONArray(); final JSONObject jsonItem = new JSONObject(); if (clientNames.contains(request.optString("name")) && typeId > 0) { UUID uuid = null; long clientUid = 0; boolean existingClient = false; final int tcAcceptedVersion = request.optInt("terms_and_conditions_accepted_version", 0); boolean tcAccepted = tcAcceptedVersion > 0; if (! tcAccepted) // for clients backwards compatibility tcAccepted = request.optBoolean("terms_and_conditions_accepted", false); final String uuidString = request.optString("uuid", ""); try { if (! Strings.isNullOrEmpty(uuidString)) uuid = UUID.fromString(uuidString); } catch (IllegalArgumentException e) // uuid invalid { } if (uuid != null && errorList.getLength() == 0) { clientUid = client.getClientByUuid(uuid); if (!client.hasError() && clientUid > 0) { existingClient = true; if (client.getTcAcceptedVersion()< tcAcceptedVersion) { client.updateTcAcceptedVersion(uuid,tcAcceptedVersion); } } } if (tcAccepted && !existingClient) { final Timestamp tstamp = java.sql.Timestamp.valueOf(new Timestamp(System .currentTimeMillis()).toString()); final Calendar timeWithZone = Helperfunctions.getTimeWithTimeZone(Helperfunctions .getTimezoneId()); client.setTimeZone(timeWithZone); client.setTime(tstamp); client.setClient_type_id(typeId); client.setTcAccepted(tcAccepted); client.setTcAcceptedVersion(tcAcceptedVersion); uuid = client.storeClient(uuid); if (client.hasError()) errorList.addError(client.getError()); else { jsonItem.put("uuid", uuid.toString()); } } if (client.getUid() > 0) { client.updateLastSeen(uuid); JSONObject mapServer = new JSONObject(); //for clients backwards compatibility, shall be obsoleted by url_map_server mapServer.put("host", getSetting("host_map_server", lang)); try { mapServer.put("port", Integer.parseInt(getSetting("port_map_server", lang))); } catch (NumberFormatException e) { mapServer.put("port",443); } mapServer.put("ssl", Boolean.parseBoolean(getSetting("ssl_map_server", lang))); jsonItem.put("map_server", mapServer); // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // HISTORY / FILTER final JSONObject subItem = new JSONObject(); final JSONArray netList = new JSONArray(); try { // deviceList: subItem.put("devices", getSyncGroupDeviceList(errorList, client)); // network_type: final PreparedStatement st = conn.prepareStatement( "SELECT DISTINCT group_name" + " FROM test t" + " JOIN network_type nt ON t.network_type=nt.uid" + " WHERE t.deleted = false AND t.status = 'FINISHED' "+ " AND (t.client_id IN (SELECT ? UNION SELECT uid FROM client WHERE sync_group_id = ? ))" + " AND group_name IS NOT NULL ORDER BY group_name;"); st.setLong(1, client.getUid()); st.setInt(2, client.getSync_group_id()); final ResultSet rs = st.executeQuery(); if (rs != null) while (rs.next()) // netList.put(Helperfunctions.getNetworkTypeName(rs.getInt("network_type"))); netList.put(rs.getString("group_name")); else errorList.addError("ERROR_DB_GET_SETTING_HISTORY_NETWORKS_SQL"); rs.close(); st.close(); subItem.put("networks", netList); } catch (final SQLException e) { e.printStackTrace(); errorList.addError("ERROR_DB_GET_SETTING_HISTORY_SQL"); // errorList.addError("ERROR_DB_GET_CLIENT_SQL"); } if (errorList.getLength() == 0) jsonItem.put("history", subItem); } //also put there: basis-urls for all services final JSONObject jsonItemURLs = new JSONObject(); jsonItemURLs.put("open_data_prefix", getSetting("url_open_data_prefix", lang)); jsonItemURLs.put("statistics", getSetting("url_statistics", lang)); jsonItemURLs.put("control_ipv4_only", getSetting("control_ipv4_only", lang)); jsonItemURLs.put("control_ipv6_only", getSetting("control_ipv6_only", lang)); jsonItemURLs.put("url_ipv4_check", getSetting("url_ipv4_check", lang)); jsonItemURLs.put("url_ipv6_check", getSetting("url_ipv6_check", lang)); jsonItemURLs.put("url_map_server", getSetting("url_map_server", lang)); jsonItem.put("urls",jsonItemURLs); final JSONObject jsonControlServerVersion = new JSONObject(); jsonControlServerVersion.put("control_server_version", RevisionHelper.getVerboseRevision()); jsonItem.put("versions", jsonControlServerVersion); /// servers final Boolean userServerSelection = request.optBoolean("user_server_selection"); // It returns false if there is no such key, or if the value is not Boolean.TRUE or the String "true". if (userServerSelection) { jsonItem.put("servers", getServers()); jsonItem.put("servers_ws", getServersWs()); jsonItem.put("servers_qos", getServersQos()); } /// qos try { final Locale locale = new Locale(lang); final QoSTestTypeDescDao testTypeDao = new QoSTestTypeDescDao(conn, locale); final JSONArray testTypeDescArray = new JSONArray(); for (QoSTestTypeDesc desc : testTypeDao.getAll()) { if (desc.getTestType()!=null) { //in case a qos module is not included but the entry hasn't beed removed from the db JSONObject json = new JSONObject(); json.put("test_type", desc.getTestType().name()); json.put("name", desc.getName()); testTypeDescArray.put(json); } } jsonItem.put("qostesttype_desc", testTypeDescArray); } catch (SQLException e) { errorList.addError("ERROR_DB_CONNECTION"); } /// android permissions final JSONArray androidPermissionStatus = request.optJSONArray("android_permission_status"); if (androidPermissionStatus != null) { final JSONArray requestAndroidPermissions = new JSONArray(); // for now request all permissions every time. see #1248 / comment:6 addRequestPermission(requestAndroidPermissions, "android.permission.ACCESS_FINE_LOCATION", true); addRequestPermission(requestAndroidPermissions, "android.permission.ACCESS_COARSE_LOCATION", true); addRequestPermission(requestAndroidPermissions, "android.permission.READ_PHONE_STATE", true); jsonItem.put("request_android_permissions", requestAndroidPermissions); } settingsList.put(jsonItem); answer.put("settings", settingsList); // debug: print settings request (JSON) // System.out.println(request); // debug: print settings response (JSON) // System.out.println(settingsList.toString(3)); } else errorList.addError("ERROR_CLIENT_VERSION"); } else errorList.addError("ERROR_DB_CONNECTION"); } catch (final JSONException e) { errorList.addError("ERROR_REQUEST_JSON"); System.out.println("Error parsing JSDON Data " + e.toString()); } else errorList.addErrorString("Expected request is missing."); try { answer.putOpt("error", errorList.getList()); } catch (final JSONException e) { System.out.println("Error saving ErrorList: " + e.toString()); } answerString = answer.toString(); // try // { // System.out.println(answer.toString(4)); // } // catch (final JSONException e) // { // e.printStackTrace(); // } answerString = answer.toString(); long elapsedTime = System.currentTimeMillis() - startTime; System.out.println(MessageFormat.format(labels.getString("NEW_SETTINGS_REQUEST_SUCCESS"), clientIpRaw, Long.toString(elapsedTime))); return answerString; } // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private static void addRequestPermission(JSONArray requestAndroidPermissions, String permission, boolean request) throws JSONException { final JSONObject requestObj = new JSONObject(); requestObj.put("permission", permission); requestObj.put("request", request); requestAndroidPermissions.put(requestObj); } private JSONArray getServers() throws JSONException { final String sql = "SELECT * FROM test_server WHERE active AND selectable AND server_type = 'RMBT'"; final JSONArray result = new JSONArray(); try (PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { while (rs.next()) { final JSONObject obj = new JSONObject(); obj.put("name", rs.getString("name")); obj.put("uuid", rs.getString("uuid")); result.put(obj); } } catch (SQLException e) { e.printStackTrace(); } return result; } // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private JSONArray getServersWs() throws JSONException { final String sql = "SELECT * FROM test_server WHERE selectable AND server_type = 'RMBTws'"; final JSONArray result = new JSONArray(); try (PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { while (rs.next()) { final JSONObject obj = new JSONObject(); obj.put("name", rs.getString("name")); obj.put("uuid", rs.getString("uuid")); result.put(obj); } } catch (SQLException e) { e.printStackTrace(); } return result; } // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private JSONArray getServersQos() throws JSONException { final String sql = "SELECT * FROM test_server WHERE selectable AND server_type = 'QoS'"; final JSONArray result = new JSONArray(); try (PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { while (rs.next()) { final JSONObject obj = new JSONObject(); obj.put("name", rs.getString("name")); obj.put("uuid", rs.getString("uuid")); result.put(obj); } } catch (SQLException e) { e.printStackTrace(); } return result; } // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * * @param entity * @return */ @Get("json") public String retrieve(final String entity) { return request(entity); } // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private JSONArray getSyncGroupDeviceList(final ErrorList errorList, final Client client) throws SQLException { JSONArray ownDeviceList = null; final PreparedStatement st = conn .prepareStatement("SELECT DISTINCT COALESCE(adm.fullname, t.model) model" + " FROM test t" + " LEFT JOIN device_map adm ON adm.codename=t.model" + " WHERE (t.client_id IN (SELECT ? UNION SELECT uid FROM client WHERE sync_group_id = ? )) AND t.deleted = false AND t.implausible = false AND t.status = 'FINISHED' ORDER BY model ASC"); st.setLong(1, client.getUid()); st.setInt(2, client.getSync_group_id()); // System.out.println(st.toString()); final ResultSet rs = st.executeQuery(); if (rs != null) { ownDeviceList = new JSONArray(); while (rs.next()) { final String model = rs.getString("model"); if (model == null || model.isEmpty()) ownDeviceList.put("Unknown Device"); else ownDeviceList.put(model); } } else errorList.addError("ERROR_DB_GET_SETTING_HISTORY_DEVICES_SQL"); rs.close(); st.close(); return ownDeviceList; } }