diff options
Diffstat (limited to 'main/src/cgeo/geocaching/network')
| -rw-r--r-- | main/src/cgeo/geocaching/network/HtmlImage.java | 30 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/network/Network.java | 23 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/network/OAuth.java | 10 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java | 58 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/network/OAuthTokens.java | 38 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/network/SmileyImage.java | 44 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/network/StatusUpdater.java | 23 |
7 files changed, 153 insertions, 73 deletions
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index 31edc9f..ab902d2 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -89,7 +89,7 @@ public class HtmlImage implements Html.ImageGetter { final private int maxWidth; final private int maxHeight; final private Resources resources; - final private TextView view; + protected final TextView view; // Background loading final private PublishSubject<Observable<String>> loading = PublishSubject.create(); @@ -154,6 +154,10 @@ public class HtmlImage implements Html.ImageGetter { if (view == null) { return drawable.toBlocking().lastOrDefault(null); } + return getContainerDrawable(drawable); + } + + protected BitmapDrawable getContainerDrawable(final Observable<BitmapDrawable> drawable) { return new ContainerDrawable(view, drawable); } @@ -162,17 +166,17 @@ public class HtmlImage implements Html.ImageGetter { public Observable<BitmapDrawable> fetchDrawable(final String url) { if (StringUtils.isBlank(url) || ImageUtils.containsPattern(url, BLOCKED)) { - return Observable.from(ImageUtils.getTransparent1x1Drawable(resources)); + return Observable.just(ImageUtils.getTransparent1x1Drawable(resources)); } // Explicit local file URLs are loaded from the filesystem regardless of their age. The IO part is short // enough to make the whole operation on the computation scheduler. if (FileUtils.isFileUrl(url)) { - return Observable.defer(new Func0<Observable<? extends BitmapDrawable>>() { + return Observable.defer(new Func0<Observable<BitmapDrawable>>() { @Override - public Observable<? extends BitmapDrawable> call() { + public Observable<BitmapDrawable> call() { final Bitmap bitmap = loadCachedImage(FileUtils.urlToFile(url), true).getLeft(); - return bitmap != null ? Observable.from(ImageUtils.scaleBitmapToFitDisplay(bitmap)) : Observable.<BitmapDrawable>empty(); + return bitmap != null ? Observable.just(ImageUtils.scaleBitmapToFitDisplay(bitmap)) : Observable.<BitmapDrawable>empty(); } }).subscribeOn(RxUtils.computationScheduler); } @@ -208,12 +212,7 @@ public class HtmlImage implements Html.ImageGetter { private Pair<BitmapDrawable, Boolean> loadFromDisk() { final Pair<Bitmap, Boolean> loadResult = loadImageFromStorage(url, pseudoGeocode, shared); - final Bitmap bitmap = loadResult.getLeft(); - return new ImmutablePair<>(bitmap != null ? - ImageUtils.scaleBitmapToFitDisplay(bitmap) : - null, - loadResult.getRight() - ); + return scaleImage(loadResult); } private void downloadAndSave(final Subscriber<? super BitmapDrawable> subscriber) { @@ -254,6 +253,15 @@ public class HtmlImage implements Html.ImageGetter { }); } + @SuppressWarnings("static-method") + protected Pair<BitmapDrawable, Boolean> scaleImage(final Pair<Bitmap, Boolean> loadResult) { + final Bitmap bitmap = loadResult.getLeft(); + return new ImmutablePair<>(bitmap != null ? + ImageUtils.scaleBitmapToFitDisplay(bitmap) : + null, + loadResult.getRight()); + } + public Observable<String> waitForEndObservable(@Nullable final CancellableHandler handler) { if (handler != null) { handler.unsubscribeIfCancelled(subscription); diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java index a49b302..e8c2b28 100644 --- a/main/src/cgeo/geocaching/network/Network.java +++ b/main/src/cgeo/geocaching/network/Network.java @@ -2,6 +2,7 @@ package cgeo.geocaching.network; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.TextUtils; @@ -26,11 +27,12 @@ import ch.boye.httpclientandroidlib.params.CoreConnectionPNames; import ch.boye.httpclientandroidlib.params.CoreProtocolPNames; import ch.boye.httpclientandroidlib.params.HttpParams; import ch.boye.httpclientandroidlib.util.EntityUtils; + +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONException; -import org.json.JSONObject; import android.content.Context; import android.net.ConnectivityManager; @@ -43,6 +45,7 @@ import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; +import java.util.regex.Pattern; public abstract class Network { @@ -51,7 +54,7 @@ public abstract class Network { /** Native user agent, taken from a Android 2.2 Nexus **/ private final static String NATIVE_USER_AGENT = "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"; - private static final String PATTERN_PASSWORD = "(?<=[\\?&])[Pp]ass(w(or)?d)?=[^&#$]+"; + private static final Pattern PATTERN_PASSWORD = Pattern.compile("(?<=[\\?&])[Pp]ass(w(or)?d)?=[^&#$]+"); private final static HttpParams clientParams = new BasicHttpParams(); @@ -63,7 +66,7 @@ public abstract class Network { } private static String hidePassword(final String message) { - return message.replaceAll(PATTERN_PASSWORD, "password=***"); + return PATTERN_PASSWORD.matcher(message).replaceAll("password=***"); } private static HttpClient getHttpClient() { @@ -107,14 +110,14 @@ public abstract class Network { * @return the HTTP response, or null in case of an encoding error params */ @Nullable - public static HttpResponse postJsonRequest(final String uri, final JSONObject json) { + public static HttpResponse postJsonRequest(final String uri, final ObjectNode json) { HttpPost request = new HttpPost(uri); request.addHeader("Content-Type", "application/json; charset=utf-8"); if (json != null) { try { request.setEntity(new StringEntity(json.toString(), CharEncoding.UTF_8)); } catch (UnsupportedEncodingException e) { - Log.e("postJsonRequest:JSON Entity: UnsupportedEncodingException"); + Log.e("postJsonRequest:JSON Entity: UnsupportedEncodingException", e); return null; } } @@ -344,14 +347,14 @@ public abstract class Network { * @return a JSON object if the request was successful and the body could be decoded, <code>null</code> otherwise */ @Nullable - public static JSONObject requestJSON(final String uri, @Nullable final Parameters params) { + public static ObjectNode requestJSON(final String uri, @Nullable final Parameters params) { final HttpResponse response = request("GET", uri, params, new Parameters("Accept", "application/json, text/javascript, */*; q=0.01"), null); final String responseData = getResponseData(response, false); if (responseData != null) { try { - return new JSONObject(responseData); - } catch (final JSONException e) { - Log.w("Network.requestJSON", e); + return (ObjectNode) JsonUtils.reader.readTree(responseData); + } catch (final IOException e) { + Log.w("requestJSON", e); } } diff --git a/main/src/cgeo/geocaching/network/OAuth.java b/main/src/cgeo/geocaching/network/OAuth.java index cfc62fc..c23ffbf 100644 --- a/main/src/cgeo/geocaching/network/OAuth.java +++ b/main/src/cgeo/geocaching/network/OAuth.java @@ -6,7 +6,6 @@ import ch.boye.httpclientandroidlib.NameValuePair; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; import java.util.ArrayList; import java.util.Date; @@ -18,8 +17,7 @@ public class OAuth { final String method, final boolean https, final Parameters params, - @Nullable final String token, - @Nullable final String tokenSecret, + final OAuthTokens tokens, final String consumerKey, final String consumerSecret) { params.put( @@ -27,7 +25,7 @@ public class OAuth { "oauth_nonce", CryptUtils.md5(Long.toString(System.currentTimeMillis())), "oauth_signature_method", "HMAC-SHA1", "oauth_timestamp", Long.toString(new Date().getTime() / 1000), - "oauth_token", StringUtils.defaultString(token), + "oauth_token", StringUtils.defaultString(tokens.getTokenPublic()), "oauth_version", "1.0"); params.sort(); @@ -36,7 +34,7 @@ public class OAuth { paramsEncoded.add(nameValue.getName() + "=" + OAuth.percentEncode(nameValue.getValue())); } - final String keysPacked = consumerSecret + "&" + StringUtils.defaultString(tokenSecret); // both even if empty some of them! + final String keysPacked = consumerSecret + "&" + StringUtils.defaultString(tokens.getTokenSecret()); // both even if empty some of them! final @NonNull String joinedParams = StringUtils.join(paramsEncoded.toArray(), '&'); final String requestPacked = method + "&" + OAuth.percentEncode((https ? "https" : "http") + "://" + host + path) + "&" + OAuth.percentEncode(joinedParams); params.put("oauth_signature", CryptUtils.base64Encode(CryptUtils.hashHmac(requestPacked, keysPacked))); @@ -48,7 +46,7 @@ public class OAuth { * @param url * @return */ - static String percentEncode(@NonNull String url) { + static String percentEncode(@NonNull final String url) { return StringUtils.replace(Network.rfc3986URLEncode(url), "*", "%2A"); } } diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java index eb56f0b..5efea02 100644 --- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java @@ -40,6 +40,8 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { private static final int STATUS_ERROR = 0; private static final int STATUS_SUCCESS = 1; private static final int STATUS_ERROR_EXT_MSG = 2; + private static final Pattern PARAMS_PATTERN_1 = Pattern.compile("oauth_token=([\\w_.-]+)"); + private static final Pattern PARAMS_PATTERN_2 = Pattern.compile("oauth_token_secret=([\\w_.-]+)"); @NonNull private String host = StringUtils.EMPTY; @NonNull private String pathRequest = StringUtils.EMPTY; @@ -51,18 +53,16 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { @NonNull private String callback = StringUtils.EMPTY; private String OAtoken = null; private String OAtokenSecret = null; - private final Pattern paramsPattern1 = Pattern.compile("oauth_token=([a-zA-Z0-9\\-\\_.]+)"); - private final Pattern paramsPattern2 = Pattern.compile("oauth_token_secret=([a-zA-Z0-9\\-\\_.]+)"); @InjectView(R.id.start) protected Button startButton; @InjectView(R.id.auth_1) protected TextView auth_1; @InjectView(R.id.auth_2) protected TextView auth_2; private ProgressDialog requestTokenDialog = null; private ProgressDialog changeTokensDialog = null; - private Handler requestTokenHandler = new Handler() { + private final Handler requestTokenHandler = new Handler() { @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { if (requestTokenDialog != null && requestTokenDialog.isShowing()) { requestTokenDialog.dismiss(); } @@ -85,10 +85,10 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { }; - private Handler changeTokensHandler = new Handler() { + private final Handler changeTokensHandler = new Handler() { @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { if (changeTokensDialog != null && changeTokensDialog.isShowing()) { changeTokensDialog.dismiss(); } @@ -105,10 +105,10 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { }; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.authorization_activity); - Bundle extras = getIntent().getExtras(); + final Bundle extras = getIntent().getExtras(); if (extras != null) { host = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_HOST, host); pathRequest = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_PATH_REQUEST, pathRequest); @@ -125,7 +125,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { auth_1.setText(getAuthExplainShort()); auth_2.setText(getAuthExplainLong()); - ImmutablePair<String, String> tempToken = getTempTokens(); + final ImmutablePair<String, String> tempToken = getTempTokens(); OAtoken = tempToken.left; OAtokenSecret = tempToken.right; @@ -167,7 +167,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { final Parameters params = new Parameters(); params.put("oauth_callback", callback); final String method = "GET"; - OAuth.signOAuth(host, pathRequest, method, https, params, null, null, consumerKey, consumerSecret); + OAuth.signOAuth(host, pathRequest, method, https, params, new OAuthTokens(null, null), consumerKey, consumerSecret); final HttpResponse response = Network.getRequest(getUrlPrefix() + host + pathRequest, params); if (Network.isSuccess(response)) { @@ -176,11 +176,11 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { int status = STATUS_ERROR; if (StringUtils.isNotBlank(line)) { assert line != null; - final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line); + final MatcherWrapper paramsMatcher1 = new MatcherWrapper(PARAMS_PATTERN_1, line); if (paramsMatcher1.find()) { OAtoken = paramsMatcher1.group(1); } - final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line); + final MatcherWrapper paramsMatcher2 = new MatcherWrapper(PARAMS_PATTERN_2, line); if (paramsMatcher2.find()) { OAtokenSecret = paramsMatcher2.group(1); } @@ -193,9 +193,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { final String encodedParams = EntityUtils.toString(new UrlEncodedFormEntity(paramsBrowser)); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getUrlPrefix() + host + pathAuthorize + "?" + encodedParams))); status = STATUS_SUCCESS; - } catch (ParseException e) { - Log.e("OAuthAuthorizationActivity.requestToken", e); - } catch (IOException e) { + } catch (ParseException | IOException e) { Log.e("OAuthAuthorizationActivity.requestToken", e); } } @@ -221,17 +219,17 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { final Parameters params = new Parameters("oauth_verifier", verifier); final String method = "POST"; - OAuth.signOAuth(host, pathAccess, method, https, params, OAtoken, OAtokenSecret, consumerKey, consumerSecret); + OAuth.signOAuth(host, pathAccess, method, https, params, new OAuthTokens(OAtoken, OAtokenSecret), consumerKey, consumerSecret); final String line = StringUtils.defaultString(Network.getResponseData(Network.postRequest(getUrlPrefix() + host + pathAccess, params))); OAtoken = ""; OAtokenSecret = ""; - final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line); + final MatcherWrapper paramsMatcher1 = new MatcherWrapper(PARAMS_PATTERN_1, line); if (paramsMatcher1.find()) { OAtoken = paramsMatcher1.group(1); } - final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line); + final MatcherWrapper paramsMatcher2 = new MatcherWrapper(PARAMS_PATTERN_2, line); if (paramsMatcher2.find() && paramsMatcher2.groupCount() > 0) { OAtokenSecret = paramsMatcher2.group(1); } @@ -244,7 +242,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { setTokens(OAtoken, OAtokenSecret, true); status = AUTHENTICATED; } - } catch (Exception e) { + } catch (final Exception e) { Log.e("OAuthAuthorizationActivity.changeToken", e); } @@ -258,7 +256,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { private class StartListener implements View.OnClickListener { @Override - public void onClick(View arg0) { + public void onClick(final View arg0) { if (requestTokenDialog == null) { requestTokenDialog = new ProgressDialog(OAuthAuthorizationActivity.this); requestTokenDialog.setCancelable(false); @@ -333,7 +331,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { * @return String with a more detailed error message (user-facing, localized), can be empty */ @SuppressWarnings("static-method") - protected String getExtendedErrorMsg(HttpResponse response) { + protected String getExtendedErrorMsg(final HttpResponse response) { return StringUtils.EMPTY; } @@ -363,14 +361,14 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { @NonNull public final String consumerSecret; @NonNull public final String callback; - public OAuthParameters(@NonNull String host, - @NonNull String pathRequest, - @NonNull String pathAuthorize, - @NonNull String pathAccess, - boolean https, - @NonNull String consumerKey, - @NonNull String consumerSecret, - @NonNull String callback) { + public OAuthParameters(@NonNull final String host, + @NonNull final String pathRequest, + @NonNull final String pathAuthorize, + @NonNull final String pathAccess, + final boolean https, + @NonNull final String consumerKey, + @NonNull final String consumerSecret, + @NonNull final String callback) { this.host = host; this.pathRequest = pathRequest; this.pathAuthorize = pathAuthorize; @@ -381,7 +379,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { this.callback = callback; } - public void setOAuthExtras(Intent intent) { + public void setOAuthExtras(final Intent intent) { if (intent != null) { intent.putExtra(Intents.EXTRA_OAUTH_HOST, host); intent.putExtra(Intents.EXTRA_OAUTH_PATH_REQUEST, pathRequest); diff --git a/main/src/cgeo/geocaching/network/OAuthTokens.java b/main/src/cgeo/geocaching/network/OAuthTokens.java new file mode 100644 index 0000000..9f45e7f --- /dev/null +++ b/main/src/cgeo/geocaching/network/OAuthTokens.java @@ -0,0 +1,38 @@ +package cgeo.geocaching.network; + +import cgeo.geocaching.connector.oc.OCApiConnector; +import cgeo.geocaching.settings.Settings; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.eclipse.jdt.annotation.NonNull; + +import android.util.Pair; + +public class OAuthTokens extends Pair<String, String> { + + public OAuthTokens(@NonNull final OCApiConnector connector) { + this(Settings.getTokenPair(connector.getTokenPublicPrefKeyId(), connector.getTokenSecretPrefKeyId())); + } + + public OAuthTokens(final ImmutablePair<String, String> tokenPair) { + this(tokenPair.left, tokenPair.right); + } + + public OAuthTokens(final String pub, final String secret) { + super(pub, secret); + } + + public boolean isValid() { + return StringUtils.isNotBlank(getTokenPublic()) && StringUtils.isNotBlank(getTokenSecret()); + } + + public String getTokenPublic() { + return first; + } + + public String getTokenSecret() { + return second; + } + +} diff --git a/main/src/cgeo/geocaching/network/SmileyImage.java b/main/src/cgeo/geocaching/network/SmileyImage.java new file mode 100644 index 0000000..86baeaa --- /dev/null +++ b/main/src/cgeo/geocaching/network/SmileyImage.java @@ -0,0 +1,44 @@ +package cgeo.geocaching.network; + +import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.utils.ImageUtils; +import cgeo.geocaching.utils.ImageUtils.LineHeightContainerDrawable; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import rx.Observable; + +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.widget.TextView; + +/** + * Specialized image class for fetching and displaying smileys in the log book. + */ +public class SmileyImage extends HtmlImage { + + public SmileyImage(final String geocode, final TextView view) { + super(geocode, false, StoredList.STANDARD_LIST_ID, false, view); + } + + @Override + protected Pair<BitmapDrawable, Boolean> scaleImage(final Pair<Bitmap, Boolean> loadResult) { + final Bitmap bitmap = loadResult.getLeft(); + BitmapDrawable drawable; + if (bitmap != null) { + drawable = new BitmapDrawable(view.getResources(), bitmap); + drawable.setBounds(ImageUtils.scaleImageToLineHeight(drawable, view)); + } + else { + drawable = null; + } + return new ImmutablePair<>(drawable, loadResult.getRight()); + } + + @Override + protected BitmapDrawable getContainerDrawable(final Observable<BitmapDrawable> drawable) { + return new LineHeightContainerDrawable(view, drawable); + } + +} diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java index 82650d1..bc4a5db 100644 --- a/main/src/cgeo/geocaching/network/StatusUpdater.java +++ b/main/src/cgeo/geocaching/network/StatusUpdater.java @@ -4,8 +4,7 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.utils.RxUtils; import cgeo.geocaching.utils.Version; -import org.json.JSONException; -import org.json.JSONObject; +import com.fasterxml.jackson.databind.node.ObjectNode; import rx.functions.Action0; import rx.subjects.BehaviorSubject; @@ -31,11 +30,11 @@ public class StatusUpdater { this.url = url; } - Status(final JSONObject response) { - message = get(response, "message"); - messageId = get(response, "message_id"); - icon = get(response, "icon"); - url = get(response, "url"); + Status(final ObjectNode response) { + message = response.path("message").asText(null); + messageId = response.path("message_id").asText(null); + icon = response.path("icon").asText(null); + url = response.path("url").asText(null); } final static public Status closeoutStatus = @@ -55,7 +54,7 @@ public class StatusUpdater { RxUtils.networkScheduler.createWorker().schedulePeriodically(new Action0() { @Override public void call() { - final JSONObject response = + final ObjectNode response = Network.requestJSON("http://status.cgeo.org/api/status.json", new Parameters("version_code", String.valueOf(Version.getVersionCode(CgeoApplication.getInstance())), "version_name", Version.getVersionName(CgeoApplication.getInstance()), @@ -67,12 +66,4 @@ public class StatusUpdater { }, 0, 1800, TimeUnit.SECONDS); } - private static String get(final JSONObject json, final String key) { - try { - return json.getString(key); - } catch (final JSONException e) { - return null; - } - } - } |
