diff options
Diffstat (limited to 'main/src/cgeo/geocaching/network')
| -rw-r--r-- | main/src/cgeo/geocaching/network/Cookies.java | 47 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/network/HtmlImage.java | 19 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/network/Login.java | 398 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/network/Network.java | 303 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/network/Parameters.java | 46 |
5 files changed, 214 insertions, 599 deletions
diff --git a/main/src/cgeo/geocaching/network/Cookies.java b/main/src/cgeo/geocaching/network/Cookies.java new file mode 100644 index 0000000..68310e6 --- /dev/null +++ b/main/src/cgeo/geocaching/network/Cookies.java @@ -0,0 +1,47 @@ +package cgeo.geocaching.network; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.CookieStore; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.cookie.BasicClientCookie; + +public abstract class Cookies { + + private static boolean cookieStoreRestored = false; + final static CookieStore cookieStore = new BasicCookieStore(); + + public static void restoreCookieStore(final String oldCookies) { + if (!cookieStoreRestored) { + clearCookies(); + if (oldCookies != null) { + for (final String cookie : StringUtils.split(oldCookies, ';')) { + final String[] split = StringUtils.split(cookie, "=", 3); + if (split.length == 3) { + final BasicClientCookie newCookie = new BasicClientCookie(split[0], split[1]); + newCookie.setDomain(split[2]); + cookieStore.addCookie(newCookie); + } + } + } + cookieStoreRestored = true; + } + } + + public static String dumpCookieStore() { + StringBuilder cookies = new StringBuilder(); + for (final Cookie cookie : cookieStore.getCookies()) { + cookies.append(cookie.getName()); + cookies.append('='); + cookies.append(cookie.getValue()); + cookies.append('='); + cookies.append(cookie.getDomain()); + cookies.append(';'); + } + return cookies.toString(); + } + + public static void clearCookies() { + cookieStore.clear(); + } +} diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index 6cb4b86..b6be931 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -1,7 +1,6 @@ package cgeo.geocaching.network; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; import cgeo.geocaching.StoredList; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.files.LocalStorage; @@ -72,16 +71,16 @@ public class HtmlImage implements Html.ImageGetter { return new BitmapDrawable(getTransparent1x1Image()); } - Bitmap imagePre = onlySave ? null : loadImageFromStorage(url); + Bitmap imagePre = loadImageFromStorage(url); // Download image and save it to the cache - if (imagePre == null || onlySave) { + if (imagePre == null) { final String absoluteURL = makeAbsoluteURL(url); if (absoluteURL != null) { try { final File file = LocalStorage.getStorageFile(geocode, url, true, true); - final HttpResponse httpResponse = Network.request(absoluteURL, null, false, file); + final HttpResponse httpResponse = Network.getRequest(absoluteURL, null, file); if (httpResponse != null) { final int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode == 200) { @@ -91,7 +90,7 @@ public class HtmlImage implements Html.ImageGetter { } } } catch (Exception e) { - Log.e(Settings.tag, "HtmlImage.getDrawable (downloading from web)", e); + Log.e("HtmlImage.getDrawable (downloading from web)", e); } } } @@ -107,7 +106,7 @@ public class HtmlImage implements Html.ImageGetter { // get image and return if (imagePre == null) { - Log.d(Settings.tag, "HtmlImage.getDrawable: Failed to obtain image"); + Log.d("HtmlImage.getDrawable: Failed to obtain image"); if (returnErrorImage) { imagePre = BitmapFactory.decodeResource(context.getResources(), R.drawable.image_not_loaded); @@ -130,7 +129,7 @@ public class HtmlImage implements Html.ImageGetter { try { imagePre = Bitmap.createScaledBitmap(imagePre, width, height, true); } catch (Exception e) { - Log.d(Settings.tag, "HtmlImage.getDrawable: Failed to scale image"); + Log.d("HtmlImage.getDrawable: Failed to scale image"); return null; } } else { @@ -158,7 +157,7 @@ public class HtmlImage implements Html.ImageGetter { final File fileSec = LocalStorage.getStorageSecFile(geocode, url, true); return loadCachedImage(fileSec); } catch (Exception e) { - Log.w(Settings.tag, "HtmlImage.getDrawable (reading cache): " + e.toString()); + Log.w("HtmlImage.getDrawable (reading cache): " + e.toString()); } return null; } @@ -182,7 +181,7 @@ public class HtmlImage implements Html.ImageGetter { } } } catch (Exception e) { - Log.e(Settings.tag, "HtmlImage.makeAbsoluteURL (parse URL)", e); + Log.e("HtmlImage.makeAbsoluteURL (parse URL)", e); } return null; } @@ -207,7 +206,7 @@ public class HtmlImage implements Html.ImageGetter { fis = new FileInputStream(file); BitmapFactory.decodeStream(fis, null, options); } catch (FileNotFoundException e) { - Log.e(Settings.tag, "HtmlImage.setSampleSize", e); + Log.e("HtmlImage.setSampleSize", e); } finally { if (fis != null) { try { diff --git a/main/src/cgeo/geocaching/network/Login.java b/main/src/cgeo/geocaching/network/Login.java deleted file mode 100644 index d5f511d..0000000 --- a/main/src/cgeo/geocaching/network/Login.java +++ /dev/null @@ -1,398 +0,0 @@ -package cgeo.geocaching.network; - -import cgeo.geocaching.R; -import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; -import cgeo.geocaching.connector.gc.GCConstants; -import cgeo.geocaching.enumerations.StatusCode; -import cgeo.geocaching.utils.BaseUtils; -import cgeo.geocaching.utils.Log; - -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.http.HttpResponse; - -import android.content.Context; -import android.graphics.drawable.BitmapDrawable; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Matcher; - -public abstract class Login { - - private final static String ENGLISH = "English▼"; - - // false = not logged in - private static boolean actualLoginStatus = false; - private static String actualUserName = ""; - private static String actualMemberStatus = ""; - private static int actualCachesFound = -1; - private static String actualStatus = ""; - - private final static Map<String, SimpleDateFormat> gcCustomDateFormats; - static { - final String[] formats = new String[] { - "MM/dd/yyyy", - "yyyy-MM-dd", - "yyyy/MM/dd", - "dd/MMM/yyyy", - "MMM/dd/yyyy", - "dd MMM yy", - "dd/MM/yyyy" - }; - - Map<String, SimpleDateFormat> map = new HashMap<String, SimpleDateFormat>(); - - for (String format : formats) { - map.put(format, new SimpleDateFormat(format, Locale.ENGLISH)); - } - - gcCustomDateFormats = Collections.unmodifiableMap(map); - } - - public static StatusCode login() { - final ImmutablePair<String, String> login = Settings.getLogin(); - - if (login == null || StringUtils.isEmpty(login.left) || StringUtils.isEmpty(login.right)) { - Login.setActualStatus(cgBase.res.getString(R.string.err_login)); - Log.e(Settings.tag, "cgeoBase.login: No login information stored"); - return StatusCode.NO_LOGIN_INFO_STORED; - } - - // res is null during the unit tests - if (cgBase.res != null) { - Login.setActualStatus(cgBase.res.getString(R.string.init_login_popup_working)); - } - HttpResponse loginResponse = Network.request("https://www.geocaching.com/login/default.aspx", null, false, false, false); - String loginData = Network.getResponseData(loginResponse); - if (loginResponse != null && loginResponse.getStatusLine().getStatusCode() == 503 && BaseUtils.matches(loginData, GCConstants.PATTERN_MAINTENANCE)) { - return StatusCode.MAINTENANCE; - } - - if (StringUtils.isBlank(loginData)) { - Log.e(Settings.tag, "cgeoBase.login: Failed to retrieve login page (1st)"); - return StatusCode.CONNECTION_FAILED; // no loginpage - } - - if (Login.getLoginStatus(loginData)) { - Log.i(Settings.tag, "Already logged in Geocaching.com as " + login.left); - Login.switchToEnglish(loginData); - return StatusCode.NO_ERROR; // logged in - } - - Network.clearCookies(); - Settings.setCookieStore(null); - - final Parameters params = new Parameters( - "__EVENTTARGET", "", - "__EVENTARGUMENT", "", - "ctl00$ContentBody$tbUsername", login.left, - "ctl00$ContentBody$tbPassword", login.right, - "ctl00$ContentBody$cbRememberMe", "on", - "ctl00$ContentBody$btnSignIn", "Login"); - final String[] viewstates = Login.getViewstates(loginData); - if (cgBase.isEmpty(viewstates)) { - Log.e(Settings.tag, "cgeoBase.login: Failed to find viewstates"); - return StatusCode.LOGIN_PARSE_ERROR; // no viewstates - } - Login.putViewstates(params, viewstates); - - loginResponse = Network.postRequest("https://www.geocaching.com/login/default.aspx", params); - loginData = Network.getResponseData(loginResponse); - - if (StringUtils.isNotBlank(loginData)) { - if (Login.getLoginStatus(loginData)) { - Log.i(Settings.tag, "Successfully logged in Geocaching.com as " + login.left); - - Login.switchToEnglish(loginData); - Settings.setCookieStore(Network.dumpCookieStore()); - - return StatusCode.NO_ERROR; // logged in - } else { - if (loginData.contains("Your username/password combination does not match.")) { - Log.i(Settings.tag, "Failed to log in Geocaching.com as " + login.left + " because of wrong username/password"); - return StatusCode.WRONG_LOGIN_DATA; // wrong login - } else { - Log.i(Settings.tag, "Failed to log in Geocaching.com as " + login.left + " for some unknown reason"); - return StatusCode.UNKNOWN_ERROR; // can't login - } - } - } else { - Log.e(Settings.tag, "cgeoBase.login: Failed to retrieve login page (2nd)"); - // FIXME: should it be CONNECTION_FAILED to match the first attempt? - return StatusCode.COMMUNICATION_ERROR; // no login page - } - } - - public static StatusCode logout() { - HttpResponse logoutResponse = Network.request("https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fdefault.aspx%3f", null, false, false, false); - String logoutData = Network.getResponseData(logoutResponse); - if (logoutResponse != null && logoutResponse.getStatusLine().getStatusCode() == 503 && BaseUtils.matches(logoutData, GCConstants.PATTERN_MAINTENANCE)) { - return StatusCode.MAINTENANCE; - } - - Network.clearCookies(); - Settings.setCookieStore(null); - return StatusCode.NO_ERROR; - } - - public static void setActualCachesFound(final int found) { - actualCachesFound = found; - } - - public static String getActualStatus() { - return actualStatus; - } - - public static void setActualStatus(final String status) { - actualStatus = status; - } - - public static boolean isActualLoginStatus() { - return actualLoginStatus; - } - - public static void setActualLoginStatus(boolean loginStatus) { - actualLoginStatus = loginStatus; - } - - public static String getActualUserName() { - return actualUserName; - } - - public static void setActualUserName(String userName) { - actualUserName = userName; - } - - public static String getActualMemberStatus() { - return actualMemberStatus; - } - - public static void setActualMemberStatus(final String memberStatus) { - actualMemberStatus = memberStatus; - } - - public static int getActualCachesFound() { - return actualCachesFound; - } - - /** - * Check if the user has been logged in when he retrieved the data. - * - * @param page - * @return <code>true</code> if user is logged in, <code>false</code> otherwise - */ - public static boolean getLoginStatus(final String page) { - if (StringUtils.isBlank(page)) { - Log.e(Settings.tag, "cgeoBase.checkLogin: No page given"); - return false; - } - - // res is null during the unit tests - if (cgBase.res != null) { - setActualStatus(cgBase.res.getString(R.string.init_login_popup_ok)); - } - - // on every page except login page - setActualLoginStatus(BaseUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME)); - if (isActualLoginStatus()) { - setActualUserName(BaseUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???")); - setActualMemberStatus(BaseUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, "???")); - setActualCachesFound(Integer.parseInt(BaseUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", ""))); - return true; - } - - // login page - setActualLoginStatus(BaseUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME_LOGIN_PAGE)); - if (isActualLoginStatus()) { - setActualUserName(Settings.getUsername()); - setActualMemberStatus(Settings.getMemberStatus()); - // number of caches found is not part of this page - return true; - } - - // res is null during the unit tests - if (cgBase.res != null) { - setActualStatus(cgBase.res.getString(R.string.init_login_popup_failed)); - } - return false; - } - - private static void switchToEnglish(String previousPage) { - if (previousPage != null && previousPage.indexOf(ENGLISH) >= 0) { - Log.i(Settings.tag, "Geocaching.com language already set to English"); - // get find count - getLoginStatus(Network.getResponseData(Network.request("http://www.geocaching.com/email/", null, false))); - } else { - final String page = Network.getResponseData(Network.request("http://www.geocaching.com/default.aspx", null, false)); - getLoginStatus(page); - if (page == null) { - Log.e(Settings.tag, "Failed to read viewstates to set geocaching.com language"); - } - final Parameters params = new Parameters( - "__EVENTTARGET", "ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem", // switch to english - "__EVENTARGUMENT", ""); - Login.transferViewstates(page, params); - final HttpResponse response = Network.postRequest("http://www.geocaching.com/default.aspx", params); - if (!Network.isSuccess(response)) { - Log.e(Settings.tag, "Failed to set geocaching.com language to English"); - } - } - } - - public static BitmapDrawable downloadAvatarAndGetMemberStatus(final Context context) { - try { - final String profile = BaseUtils.replaceWhitespace(Network.getResponseData(Network.request("http://www.geocaching.com/my/", null, false))); - - Settings.setMemberStatus(BaseUtils.getMatch(profile, GCConstants.PATTERN_MEMBER_STATUS, true, null)); - - setActualCachesFound(Integer.parseInt(BaseUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", ""))); - - final String avatarURL = BaseUtils.getMatch(profile, GCConstants.PATTERN_AVATAR_IMAGE_PROFILE_PAGE, false, null); - if (null != avatarURL) { - final HtmlImage imgGetter = new HtmlImage(context, "", false, 0, false); - return imgGetter.getDrawable(avatarURL); - } - // No match? There may be no avatar set by user. - Log.d(Settings.tag, "No avatar set for user"); - } catch (Exception e) { - Log.w(Settings.tag, "Error when retrieving user avatar", e); - } - return null; - } - - /** - * Detect user date settings on geocaching.com - */ - public static void detectGcCustomDate() { - - final String result = Network.getResponseData(Network.request("http://www.geocaching.com/account/ManagePreferences.aspx", null, false, false, false)); - - if (null == result) { - Log.w(Settings.tag, "cgeoBase.detectGcCustomDate: result is null"); - return; - } - - String customDate = BaseUtils.getMatch(result, GCConstants.PATTERN_CUSTOMDATE, true, null); - if (null != customDate) { - Settings.setGcCustomDate(customDate); - } - } - - public static Date parseGcCustomDate(final String input, final String format) throws ParseException { - if (StringUtils.isBlank(input)) { - throw new ParseException("Input is null", 0); - } - - final String trimmed = input.trim(); - - if (gcCustomDateFormats.containsKey(format)) { - try { - return gcCustomDateFormats.get(format).parse(trimmed); - } catch (ParseException e) { - } - } - - for (SimpleDateFormat sdf : gcCustomDateFormats.values()) { - try { - return sdf.parse(trimmed); - } catch (ParseException e) { - } - } - - throw new ParseException("No matching pattern", 0); - } - - public static Date parseGcCustomDate(final String input) throws ParseException { - return parseGcCustomDate(input, Settings.getGcCustomDate()); - } - - /** - * read all viewstates from page - * - * @return String[] with all view states - */ - public static String[] getViewstates(String page) { - // Get the number of viewstates. - // If there is only one viewstate, __VIEWSTATEFIELDCOUNT is not present - - if (page == null) { // no network access - return null; - } - - int count = 1; - final Matcher matcherViewstateCount = GCConstants.PATTERN_VIEWSTATEFIELDCOUNT.matcher(page); - if (matcherViewstateCount.find()) { - try { - count = Integer.parseInt(matcherViewstateCount.group(1)); - } catch (NumberFormatException e) { - Log.e(Settings.tag, "getViewStates", e); - } - } - - String[] viewstates = new String[count]; - - // Get the viewstates - int no; - final Matcher matcherViewstates = GCConstants.PATTERN_VIEWSTATES.matcher(page); - while (matcherViewstates.find()) { - String sno = matcherViewstates.group(1); // number of viewstate - if (sno.length() == 0) { - no = 0; - } - else { - try { - no = Integer.parseInt(sno); - } catch (NumberFormatException e) { - Log.e(Settings.tag, "getViewStates", e); - no = 0; - } - } - viewstates[no] = matcherViewstates.group(2); - } - - if (viewstates.length != 1 || viewstates[0] != null) { - return viewstates; - } - // no viewstates were present - return null; - } - - /** - * put viewstates into request parameters - */ - public static void putViewstates(final Parameters params, final String[] viewstates) { - if (ArrayUtils.isEmpty(viewstates)) { - return; - } - params.put("__VIEWSTATE", viewstates[0]); - if (viewstates.length > 1) { - for (int i = 1; i < viewstates.length; i++) { - params.put("__VIEWSTATE" + i, viewstates[i]); - } - params.put("__VIEWSTATEFIELDCOUNT", String.valueOf(viewstates.length)); - } - } - - /** - * transfers the viewstates variables from a page (response) to parameters - * (next request) - */ - public static void transferViewstates(final String page, final Parameters params) { - putViewstates(params, getViewstates(page)); - } - - static public String[] requestViewstates(final String uri, final Parameters params, boolean xContentType, boolean my) { - final HttpResponse response = Network.request(uri, params, xContentType, my, false); - - return getViewstates(Network.getResponseData(response)); - } - -} diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java index 502db33..bb5a949 100644 --- a/main/src/cgeo/geocaching/network/Network.java +++ b/main/src/cgeo/geocaching/network/Network.java @@ -1,13 +1,9 @@ package cgeo.geocaching.network; -import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; -import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.Log; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; import org.apache.http.HeaderElement; @@ -18,17 +14,13 @@ import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; import org.apache.http.NameValuePair; -import org.apache.http.client.CookieStore; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.cookie.Cookie; import org.apache.http.entity.HttpEntityWrapper; -import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.CoreConnectionPNames; import org.apache.http.params.CoreProtocolPNames; @@ -44,11 +36,10 @@ import android.net.Uri; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import java.util.List; import java.util.zip.GZIPInputStream; - public abstract class Network { static class GzipDecompressingEntity extends HttpEntityWrapper { @@ -76,8 +67,6 @@ public abstract class Network { private static final String PATTERN_PASSWORD = "(?<=[\\?&])[Pp]ass(w(or)?d)?=[^&#$]+"; private final static HttpParams clientParams = new BasicHttpParams(); - private static boolean cookieStoreRestored = false; - private final static CookieStore cookieStore = new BasicCookieStore(); static { Network.clientParams.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, HTTP.UTF_8); @@ -91,7 +80,7 @@ public abstract class Network { private static HttpClient getHttpClient() { final DefaultHttpClient client = new DefaultHttpClient(); - client.setCookieStore(cookieStore); + client.setCookieStore(Cookies.cookieStore); client.setParams(clientParams); client.addRequestInterceptor(new HttpRequestInterceptor() { @@ -117,7 +106,7 @@ public abstract class Network { HeaderElement[] codecs = ceheader.getElements(); for (int i = 0; i < codecs.length; i++) { if (codecs[i].getName().equalsIgnoreCase("gzip")) { - Log.d(Settings.tag, "Decompressing response"); + Log.d("Decompressing response"); response.setEntity( new Network.GzipDecompressingEntity(response.getEntity())); return; @@ -132,40 +121,6 @@ public abstract class Network { return client; } - public static void restoreCookieStore(final String oldCookies) { - if (!cookieStoreRestored) { - Network.clearCookies(); - if (oldCookies != null) { - for (final String cookie : StringUtils.split(oldCookies, ';')) { - final String[] split = StringUtils.split(cookie, "=", 3); - if (split.length == 3) { - final BasicClientCookie newCookie = new BasicClientCookie(split[0], split[1]); - newCookie.setDomain(split[2]); - cookieStore.addCookie(newCookie); - } - } - } - cookieStoreRestored = true; - } - } - - public static String dumpCookieStore() { - StringBuilder cookies = new StringBuilder(); - for (final Cookie cookie : cookieStore.getCookies()) { - cookies.append(cookie.getName()); - cookies.append('='); - cookies.append(cookie.getValue()); - cookies.append('='); - cookies.append(cookie.getDomain()); - cookies.append(';'); - } - return cookies.toString(); - } - - public static void clearCookies() { - cookieStore.clear(); - } - /** * POST HTTP request * @@ -173,117 +128,148 @@ public abstract class Network { * @param params * @return */ - public static HttpResponse postRequest(final String uri, final List<? extends NameValuePair> params) { - try { - HttpPost request = new HttpPost(uri); - if (params != null) { - request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); - } - request.setHeader("X-Requested-With", "XMLHttpRequest"); - return Network.request(request); - } catch (Exception e) { - // Can be UnsupportedEncodingException, ClientProtocolException or IOException - Log.e(Settings.tag, "postRequest", e); - return null; - } - } - - /** - * GET HTTP request - * - * @param uri - * @param params - * @param xContentType - * @param my - * @param addF - * @return - */ - public static HttpResponse request(final String uri, final Parameters params, boolean xContentType, boolean my, boolean addF) { - return Network.request(uri, cgBase.addFToParams(params, my, addF), xContentType); + public static HttpResponse postRequest(final String uri, final Parameters params) { + return request("POST", uri, params, null, null); } /** - * GET HTTP request + * Make an HTTP request * + * @param method + * the HTTP method to use ("GET" or "POST") * @param uri + * the URI to request * @param params - * @param xContentType + * the parameters to add the the GET request + * @param headers + * the headers to add to the GET request * @param cacheFile - * the name of the file storing the cached resource, or null not to use one - * @return + * the cache file used to cache this query + * @return the HTTP response, or null in case of an encoding error in a POST request arguments */ - public static HttpResponse request(final String uri, final Parameters params, final boolean xContentType, final File cacheFile) { - final String fullUri = params == null ? uri : Uri.parse(uri).buildUpon().encodedQuery(params.toString()).build().toString(); - final HttpRequestBase request = new HttpGet(fullUri); + private static HttpResponse request(final String method, final String uri, final Parameters params, final Parameters headers, final File cacheFile) { + HttpRequestBase request; + if (method.equals("GET")) { + final String fullUri = params == null ? uri : Uri.parse(uri).buildUpon().encodedQuery(params.toString()).build().toString(); + request = new HttpGet(fullUri); + } else { + request = new HttpPost(uri); + if (params != null) { + try { + ((HttpPost) request).setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); + } catch (final UnsupportedEncodingException e) { + Log.e("request", e); + return null; + } + } + } - request.setHeader("X-Requested-With", "XMLHttpRequest"); + for (final NameValuePair header : Parameters.extend(Parameters.merge(headers, cacheHeaders(cacheFile)), + "Accept-Charset", "utf-8,iso-8859-1;q=0.8,utf-16;q=0.8,*;q=0.7", + "Accept-Language", "en-US,*;q=0.9", + "X-Requested-With", "XMLHttpRequest")) { + request.setHeader(header.getName(), header.getValue()); + } + + request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, Network.USER_AGENT); - if (xContentType) { - request.setHeader("Content-Type", "application/x-www-form-urlencoded"); + final String reqLogStr = request.getMethod() + " " + Network.hidePassword(request.getURI().toString()); + Log.d(reqLogStr); + + final HttpClient client = Network.getHttpClient(); + for (int i = 0; i <= Network.NB_DOWNLOAD_RETRIES; i++) { + final long before = System.currentTimeMillis(); + try { + final HttpResponse response = client.execute(request); + int status = response.getStatusLine().getStatusCode(); + if (status == 200) { + Log.d(status + Network.formatTimeSpan(before) + reqLogStr); + } else { + Log.w(status + " [" + response.getStatusLine().getReasonPhrase() + "]" + Network.formatTimeSpan(before) + reqLogStr); + } + return response; + } catch (IOException e) { + final String timeSpan = Network.formatTimeSpan(before); + final String tries = (i + 1) + "/" + (Network.NB_DOWNLOAD_RETRIES + 1); + if (i == Network.NB_DOWNLOAD_RETRIES) { + Log.e("Failure " + tries + timeSpan + reqLogStr, e); + } else { + Log.e("Failure " + tries + " (" + e.toString() + ")" + timeSpan + "- retrying " + reqLogStr); + } + } } + return null; + } + + private static Parameters cacheHeaders(final File cacheFile) { if (cacheFile != null && cacheFile.exists()) { final String etag = LocalStorage.getSavedHeader(cacheFile, "etag"); if (etag != null) { - request.setHeader("If-None-Match", etag); + return new Parameters("If-None-Match", etag); } else { final String lastModified = LocalStorage.getSavedHeader(cacheFile, "last-modified"); if (lastModified != null) { - request.setHeader("If-Modified-Since", lastModified); + return new Parameters("If-Modified-Since", lastModified); } } } - - return Network.request(request); + return null; } /** * GET HTTP request * * @param uri + * the URI to request * @param params - * @param xContentType - * @return + * the parameters to add the the GET request + * @param cacheFile + * the name of the file storing the cached resource, or null not to use one + * @return the HTTP response */ - public static HttpResponse request(final String uri, final Parameters params, final boolean xContentType) { - return request(uri, params, xContentType, null); + public static HttpResponse getRequest(final String uri, final Parameters params, final File cacheFile) { + return request("GET", uri, params, null, cacheFile); } - public static HttpResponse request(final HttpRequestBase request) { - request.setHeader("Accept-Charset", "utf-8,iso-8859-1;q=0.8,utf-16;q=0.8,*;q=0.7"); - request.setHeader("Accept-Language", "en-US,*;q=0.9"); - request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, USER_AGENT); - return Network.doRequest(request); - } - private static HttpResponse doRequest(final HttpRequestBase request) { - final String reqLogStr = request.getMethod() + " " + hidePassword(request.getURI().toString()); - Log.d(Settings.tag, reqLogStr); + /** + * GET HTTP request + * + * @param uri + * the URI to request + * @param params + * the parameters to add the the GET request + * @return the HTTP response + */ + public static HttpResponse getRequest(final String uri, final Parameters params) { + return request("GET", uri, params, null, null); + } - final HttpClient client = getHttpClient(); - for (int i = 0; i <= NB_DOWNLOAD_RETRIES; i++) { - final long before = System.currentTimeMillis(); - try { - final HttpResponse response = client.execute(request); - int status = response.getStatusLine().getStatusCode(); - if (status == 200) { - Log.d(Settings.tag, status + Network.formatTimeSpan(before) + reqLogStr); - } else { - Log.w(Settings.tag, status + " [" + response.getStatusLine().getReasonPhrase() + "]" + Network.formatTimeSpan(before) + reqLogStr); - } - return response; - } catch (IOException e) { - final String timeSpan = Network.formatTimeSpan(before); - final String tries = (i + 1) + "/" + (NB_DOWNLOAD_RETRIES + 1); - if (i == NB_DOWNLOAD_RETRIES) { - Log.e(Settings.tag, "Failure " + tries + timeSpan + reqLogStr, e); - } else { - Log.e(Settings.tag, "Failure " + tries + " (" + e.toString() + ")" + timeSpan + "- retrying " + reqLogStr); - } - } - } + /** + * GET HTTP request + * + * @param uri + * the URI to request + * @param params + * the parameters to add the the GET request + * @param headers + * the headers to add to the GET request + * @return the HTTP response + */ + public static HttpResponse getRequest(final String uri, final Parameters params, final Parameters headers) { + return request("GET", uri, params, headers, null); + } - return null; + /** + * GET HTTP request + * + * @param uri + * the URI to request + * @return the HTTP response + */ + public static HttpResponse getRequest(final String uri) { + return request("GET", uri, null, null, null); } private static String formatTimeSpan(final long before) { @@ -296,33 +282,24 @@ public abstract class Network { } public static JSONObject requestJSON(final String uri, final Parameters params) { - final HttpGet request = new HttpGet(Network.prepareParameters(uri, params)); - request.setHeader("Accept", "application/json, text/javascript, */*; q=0.01"); - request.setHeader("Content-Type", "application/json; charset=UTF-8"); - request.setHeader("X-Requested-With", "XMLHttpRequest"); - - final HttpResponse response = doRequest(request); - if (response != null && response.getStatusLine().getStatusCode() == 200) { + final HttpResponse response = request("GET", uri, params, new Parameters("Accept", "application/json, text/javascript, */*; q=0.01"), null); + if (isSuccess(response)) { try { return new JSONObject(Network.getResponseData(response)); - } catch (JSONException e) { - Log.e(Settings.tag, "Network.requestJSON", e); + } catch (final JSONException e) { + Log.e("Network.requestJSON", e); } } return null; } - private static String prepareParameters(final String baseUri, final Parameters params) { - return CollectionUtils.isNotEmpty(params) ? baseUri + "?" + params.toString() : baseUri; - } - private static String getResponseDataNoError(final HttpResponse response, boolean replaceWhitespace) { try { String data = EntityUtils.toString(response.getEntity(), HTTP.UTF_8); return replaceWhitespace ? BaseUtils.replaceWhitespace(data) : data; } catch (Exception e) { - Log.e(Settings.tag, "getResponseData", e); + Log.e("getResponseData", e); return null; } } @@ -331,59 +308,13 @@ public abstract class Network { return Network.getResponseData(response, true); } - static public String getResponseData(final HttpResponse response, boolean replaceWhitespace) { + public static String getResponseData(final HttpResponse response, boolean replaceWhitespace) { if (!isSuccess(response)) { return null; } return getResponseDataNoError(response, replaceWhitespace); } - /** - * POST HTTP request. Do the request a second time if the user is not logged in - * - * @param uri - * @return - */ - public static String postRequestLogged(final String uri) { - HttpResponse response = postRequest(uri, null); - String data = getResponseData(response); - - if (!Login.getLoginStatus(data)) { - if (Login.login() == StatusCode.NO_ERROR) { - response = postRequest(uri, null); - data = getResponseData(response); - } else { - Log.i(Settings.tag, "Working as guest."); - } - } - return data; - } - - /** - * GET HTTP request. Do the request a second time if the user is not logged in - * - * @param uri - * @param params - * @param xContentType - * @param my - * @param addF - * @return - */ - public static String requestLogged(final String uri, final Parameters params, boolean xContentType, boolean my, boolean addF) { - HttpResponse response = request(uri, params, xContentType, my, addF); - String data = getResponseData(response); - - if (!Login.getLoginStatus(data)) { - if (Login.login() == StatusCode.NO_ERROR) { - response = request(uri, params, xContentType, my, addF); - data = getResponseData(response); - } else { - Log.i(Settings.tag, "Working as guest."); - } - } - return data; - } - public static String urlencode_rfc3986(String text) { return StringUtils.replace(URLEncoder.encode(text).replace("+", "%20"), "%7E", "~"); } diff --git a/main/src/cgeo/geocaching/network/Parameters.java b/main/src/cgeo/geocaching/network/Parameters.java index e65bec2..5c0328a 100644 --- a/main/src/cgeo/geocaching/network/Parameters.java +++ b/main/src/cgeo/geocaching/network/Parameters.java @@ -12,7 +12,7 @@ import java.util.Comparator; /** * List of key/values pairs to be used in a GET or POST request. - * + * */ public class Parameters extends ArrayList<NameValuePair> { @@ -44,14 +44,16 @@ public class Parameters extends ArrayList<NameValuePair> { * list of key/value pairs * @throws InvalidParameterException * if the number of key/values is unbalanced + * @return the object itself to facilitate chaining */ - public void put(final String... keyValues) { + public Parameters put(final String... keyValues) { if (keyValues.length % 2 == 1) { throw new InvalidParameterException("odd number of parameters"); } for (int i = 0; i < keyValues.length; i += 2) { add(new BasicNameValuePair(keyValues[i], keyValues[i + 1])); } + return this; } /** @@ -63,12 +65,46 @@ public class Parameters extends ArrayList<NameValuePair> { Collections.sort(this, comparator); } - /** - * @return the URL encoded string corresponding to those parameters - */ @Override public String toString() { return URLEncodedUtils.format(this, HTTP.UTF_8); } + /** + * Extend or create a Parameters object with new key/value pairs. + * + * @param params + * an existing object or null to create a new one + * @param keyValues + * list of key/value pair + * @throws InvalidParameterException + * if the number of key/values is unbalanced + * @return the object itself if it is non-null, a new one otherwise + */ + public static Parameters extend(final Parameters params, final String... keyValues) { + if (params == null) { + return new Parameters(keyValues); + } else { + return params.put(keyValues); + } + } + + /** + * Merge two (possibly null) Parameters object. + * + * @param params + * the object to merge into if non-null + * @param extra + * the object to merge from if non-null + * @return params with extra data if params was non-null, extra otherwise + */ + public static Parameters merge(final Parameters params, final Parameters extra) { + if (params == null) { + return extra; + } else if (extra != null) { + params.addAll(extra); + } + return params; + } + } |
