| package org.wordpress.android.ui.accounts.helpers; |
| |
| import android.text.TextUtils; |
| import android.webkit.URLUtil; |
| |
| import org.json.JSONArray; |
| import org.json.JSONException; |
| import org.json.JSONObject; |
| import org.wordpress.android.util.AppLog; |
| |
| import java.io.BufferedReader; |
| import java.io.InputStreamReader; |
| import java.net.HttpURLConnection; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * |
| * This class can test a WordPress installation for plugins/themes that cause problems with WordPress for Android connecting correctly. |
| * |
| * The tool is a black box scanner, it allows remote testing of a WordPress installation. |
| * Find problematic plugins and themes, configuration issues and other glitches that can cause problems with our apps. |
| * |
| */ |
| public class PluginsCheckerWPOrg { |
| private final static String BB_PLUGINS_LIST_URL = "https://raw.githubusercontent.com/wordpress-mobile/app-blocking-plugins/master/xmlrpc-plugins.json"; |
| |
| // Do not use the WP-APP user agent. Requests could be blocked if made from our app UA. |
| private final static String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36"; |
| |
| /** Socket timeout in milliseconds for the requests */ |
| private static final int REQUEST_TIMEOUT_MS = 30000; |
| |
| String mOriginalURL; |
| |
| public PluginsCheckerWPOrg(String url) { |
| mOriginalURL = url; |
| } |
| |
| /** |
| * This routine does a black box scanning on the plugis folder of the remote host, and tries to find plugins that cause |
| * problems connecting to the host from one of our mobile apps. |
| */ |
| public List<Plugin> checkForPlugins() { |
| String responseHTML = downloadPluginsList(); |
| if (TextUtils.isEmpty(responseHTML)) { |
| AppLog.w(AppLog.T.NUX, "Without the list we can't check if the host has some BB plugins installed on it."); |
| return null; |
| } |
| |
| JSONArray listOfPlugins; |
| try { |
| listOfPlugins = new JSONArray(responseHTML); |
| } catch (JSONException e) { |
| AppLog.e(AppLog.T.NUX, "Error while parsing the list of plugins returned from the server.", e); |
| return null; |
| } |
| |
| // we have the list. Start the process of checking for plugins |
| String baseURL = getBaseURL(mOriginalURL); |
| |
| if (!baseURL.contains("/plugins")) { |
| baseURL = baseURL + "/wp-content/plugins/"; |
| } |
| |
| AppLog.i(AppLog.T.NUX, "The calculated plugins URL is the following: " + baseURL); |
| |
| if (!URLUtil.isValidUrl(baseURL)) { |
| AppLog.w(AppLog.T.NUX, "The calculated plugins URL isn't a valid URL. Returning now."); |
| return null; |
| } |
| |
| int respCode = openConnection(baseURL); |
| if (respCode != HttpURLConnection.HTTP_OK && respCode != 401 && respCode != 403) { |
| AppLog.w(AppLog.T.NUX, "The request to plugins URL returned with an unexpected HTTP error code. Returning now."); |
| return null; |
| } |
| |
| AppLog.i(AppLog.T.NUX, "Start checking the plugins list.."); |
| ArrayList<Plugin> listOfBBPlugins = new ArrayList<>(); |
| for (int i=0; i<listOfPlugins.length(); i++) { |
| try { |
| JSONObject currentObject = listOfPlugins.getJSONObject(i); |
| String currentPluginURL = baseURL + currentObject.getString("name") + "/"; |
| AppLog.i(AppLog.T.NUX, "Testing the following plugin " + currentPluginURL); |
| respCode = openConnection(currentPluginURL); |
| if (respCode != HttpURLConnection.HTTP_NOT_FOUND) { |
| Plugin currentBBPLugin = new Plugin(); |
| currentBBPLugin.name = currentObject.getString("name"); |
| currentBBPLugin.url = currentObject.getString("url"); |
| listOfBBPlugins.add(currentBBPLugin); |
| AppLog.i(AppLog.T.NUX, "Plugin found on the server: " + currentObject.getString("name")); |
| } else { |
| AppLog.i(AppLog.T.NUX, "Plugin NOT found on the server: " + currentObject.getString("name")); |
| } |
| } catch (JSONException e) { |
| AppLog.e(AppLog.T.NUX, "Error while parsing the " + i + " in the list of plugins returned from the server.", e); |
| } |
| } |
| |
| return listOfBBPlugins; |
| } |
| |
| private String downloadPluginsList() { |
| HttpURLConnection conn = null; |
| String response = ""; |
| try { |
| URL url = new URL(BB_PLUGINS_LIST_URL); |
| conn = (HttpURLConnection) url.openConnection(); |
| conn.setReadTimeout(REQUEST_TIMEOUT_MS); |
| conn.setConnectTimeout(REQUEST_TIMEOUT_MS); |
| conn.setRequestProperty("User-Agent", USER_AGENT); |
| conn.setUseCaches(false); |
| conn.setRequestProperty("Connection", "close"); |
| conn.setRequestMethod("GET"); |
| BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); |
| String inLine; |
| while ((inLine = in.readLine()) != null) { |
| response += inLine; |
| } |
| } catch (Exception e) { |
| AppLog.e(AppLog.T.NUX, "Error while downloading the plugins list from the server...", e); |
| } finally { |
| try { |
| if (conn != null) { |
| conn.disconnect(); |
| } |
| } catch (Exception e) { |
| } |
| } |
| return response; |
| } |
| |
| private int openConnection(String url) { |
| HttpURLConnection conn = null; |
| try { |
| URL requestURL = new URL(url); |
| conn = (HttpURLConnection) requestURL.openConnection(); |
| conn.setReadTimeout(REQUEST_TIMEOUT_MS); |
| conn.setConnectTimeout(REQUEST_TIMEOUT_MS); |
| conn.setRequestProperty("User-Agent", USER_AGENT); |
| conn.setUseCaches(false); |
| conn.setRequestProperty("Connection", "close"); |
| conn.setRequestMethod("GET"); |
| conn.connect(); |
| int respCode = conn.getResponseCode(); |
| return respCode; |
| } catch (Exception e) { |
| AppLog.e(AppLog.T.NUX, "Error while checking for the plugins folder on the server.", e); |
| } finally { |
| try { |
| if (conn != null) { |
| conn.disconnect(); |
| } |
| } catch (Exception e) { |
| } |
| |
| } |
| return 0; |
| } |
| |
| private String getBaseURL(String url) { |
| String sanitizedURL = url; |
| try { |
| sanitizedURL = truncateURLAtPrefix(sanitizedURL, "wp-login.php" ); |
| sanitizedURL = truncateURLAtPrefix(sanitizedURL, "/wp-admin" ); |
| sanitizedURL = truncateURLAtPrefix(sanitizedURL, "/wp-content" ); |
| sanitizedURL = truncateURLAtPrefix(sanitizedURL, "/xmlrpc.php" ); |
| } catch (IllegalArgumentException e) { |
| AppLog.e(AppLog.T.NUX, "Can't clean the original url: " + sanitizedURL, e); |
| } |
| while (sanitizedURL.endsWith("/")) { |
| sanitizedURL = sanitizedURL.substring(0, sanitizedURL.length() - 1); |
| } |
| return sanitizedURL; |
| } |
| |
| private String truncateURLAtPrefix(String url, String prefix) throws IllegalArgumentException { |
| if (!URLUtil.isValidUrl(url)) { |
| throw new IllegalArgumentException("Input URL " + url + " is not valid!"); |
| } |
| if (TextUtils.isEmpty(prefix)) { |
| throw new IllegalArgumentException("Input prefix is empty or null"); |
| } |
| |
| if (url.indexOf(prefix) > 0) { |
| url = url.substring(0, url.indexOf(prefix)); |
| } |
| |
| if (!URLUtil.isValidUrl(url)) { |
| throw new IllegalArgumentException("The new URL " + url + " is not valid!"); |
| } |
| |
| return url; |
| } |
| |
| public class Plugin { |
| String name; |
| String url; |
| } |
| } |