diff options
author | Vincent Breitmoser <valodim@mugenguild.com> | 2015-03-12 20:46:50 +0100 |
---|---|---|
committer | Vincent Breitmoser <valodim@mugenguild.com> | 2015-03-12 20:46:50 +0100 |
commit | a5e8825882a986bd25455a56e2eab2778fbdf75e (patch) | |
tree | 2d81b178fe4d2f123a2c5dae186ce03c8c990c6b /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp | |
parent | 8d71a3fa92c9a9b690c547cbb970b2a5924c10d6 (diff) | |
download | open-keychain-a5e8825882a986bd25455a56e2eab2778fbdf75e.tar.gz open-keychain-a5e8825882a986bd25455a56e2eab2778fbdf75e.tar.bz2 open-keychain-a5e8825882a986bd25455a56e2eab2778fbdf75e.zip |
finish implementing twitter resource
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp')
3 files changed, 171 insertions, 62 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java index 84b79920a..c92624f65 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java @@ -107,7 +107,7 @@ public abstract class LinkedCookieResource extends LinkedResource { String candidateFp = match.group(1).toLowerCase(); try { - int nonceCandidate = Integer.parseInt(match.group(2).toLowerCase(), 16); + int nonceCandidate = (int) Long.parseLong(match.group(2).toLowerCase(), 16); if (nonce != nonceCandidate) { log.add(LogType.MSG_LV_NONCE_ERROR, indent); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java index ff5995329..d529a2a36 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java @@ -3,7 +3,6 @@ package org.sufficientlysecure.keychain.pgp.linked; import org.spongycastle.bcpg.UserAttributeSubpacket; import org.spongycastle.util.Strings; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; import org.sufficientlysecure.keychain.util.Log; @@ -13,7 +12,6 @@ import java.nio.ByteBuffer; import java.util.Arrays; import android.content.Context; -import android.content.Intent; import android.support.annotation.DrawableRes; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java index 3553ce740..d00fa7ece 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java @@ -1,22 +1,25 @@ package org.sufficientlysecure.keychain.pgp.linked.resources; import android.content.Context; +import android.content.Intent; +import android.net.Uri; import android.support.annotation.DrawableRes; -import android.util.Base64; +import android.util.Log; import com.textuality.keybase.lib.JWalk; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; -import org.apache.http.client.ClientProtocolException; 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.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.BasicHttpParams; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.pgp.linked.LinkedCookieResource; @@ -27,14 +30,47 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URI; -import java.net.URLEncoder; import java.util.HashMap; +import java.util.HashSet; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class TwitterResource extends LinkedCookieResource { - TwitterResource(Set<String> flags, HashMap<String,String> params, URI uri) { + final String mHandle; + final String mTweetId; + + TwitterResource(Set<String> flags, HashMap<String,String> params, + URI uri, String handle, String tweetId) { super(flags, params, uri); + + mHandle = handle; + mTweetId = tweetId; + } + + public static TwitterResource create(URI uri) { + return create(new HashSet<String>(), new HashMap<String,String>(), uri); + } + + public static TwitterResource create(Set<String> flags, HashMap<String,String> params, URI uri) { + + // no params or flags + if (!flags.isEmpty() || !params.isEmpty()) { + return null; + } + + Pattern p = Pattern.compile("https://twitter.com/([a-zA-Z0-9_]+)/status/([0-9]+)"); + Matcher match = p.matcher(uri.toString()); + if (!match.matches()) { + return null; + } + String handle = match.group(1); + String tweetId = match.group(2); + + return new TwitterResource(flags, params, uri, handle, tweetId); + } public static String generateText (Context context, byte[] fingerprint, int nonce) { @@ -42,21 +78,127 @@ public class TwitterResource extends LinkedCookieResource { return LinkedCookieResource.generate(context, fingerprint, nonce); } - private String getTwitterStream(String screenName) { - String results = null; + @Override + protected String fetchResource(OperationLog log, int indent) { + + String authToken = getAuthToken(); + + if (authToken == null) { + return null; + } + + HttpGet httpGet = + new HttpGet("https://api.twitter.com/1.1/statuses/show.json" + + "?id=" + mTweetId + + "&include_entities=false"); + + // construct a normal HTTPS request and include an Authorization + // header with the value of Bearer <> + httpGet.setHeader("Authorization", "Bearer " + authToken); + httpGet.setHeader("Content-Type", "application/json"); - // Step 1: Encode consumer key and secret try { - // URL encode the consumer key and secret - String urlApiKey = URLEncoder.encode("6IhPnWbYxASAoAzH2QaUtHD0J", "UTF-8"); - String urlApiSecret = URLEncoder.encode("L0GnuiOnapWbSBbQtLIqtpeS5BTtvh06dmoMoKQfHQS8UwHuWm", "UTF-8"); + String response = getResponseBody(httpGet); + JSONObject obj = new JSONObject(response); + + if (!obj.has("text")) { + return null; + } + + JSONObject user = obj.getJSONObject("user"); + if (!mHandle.equalsIgnoreCase(user.getString("screen_name"))) { + return null; + } - // Concatenate the encoded consumer key, a colon character, and the - // encoded consumer secret - String combined = urlApiKey + ":" + urlApiSecret; + // update the results with the body of the response + return obj.getString("text"); + } catch (JSONException e) { + Log.e(Constants.TAG, "json error parsing stream", e); + return null; + } + + } + + @Override + public @DrawableRes int getDisplayIcon() { + return R.drawable.twitter; + } - // Base64 encode the string - String base64Encoded = Base64.encodeToString(combined.getBytes(), Base64.NO_WRAP); + @Override + public String getDisplayTitle(Context context) { + return "Twitter"; + } + + @Override + public String getDisplayComment(Context context) { + return "@" + mHandle; + } + + @Override + public boolean isViewable() { + return true; + } + + @Override + public Intent getViewIntent() { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(mSubUri.toString())); + return intent; + } + + public static TwitterResource searchInTwitterStream(String screenName, String needle) { + + String authToken = getAuthToken(); + + if (authToken == null) { + return null; + } + + HttpGet httpGet = + new HttpGet("https://api.twitter.com/1.1/statuses/user_timeline.json" + + "?screen_name=" + screenName + + "&count=15" + + "&include_rts=false" + + "&trim_user=true" + + "&exclude_replies=true"); + + // construct a normal HTTPS request and include an Authorization + // header with the value of Bearer <> + httpGet.setHeader("Authorization", "Bearer " + authToken); + httpGet.setHeader("Content-Type", "application/json"); + + try { + String response = getResponseBody(httpGet); + JSONArray array = new JSONArray(response); + + for (int i = 0; i < array.length(); i++) { + JSONObject obj = array.getJSONObject(i); + String tweet = obj.getString("text"); + if (tweet.contains(needle)) { + String id = obj.getString("id_str"); + URI uri = URI.create("https://twitter.com/" + screenName + "/status/" + id); + return create(uri); + } + } + + // update the results with the body of the response + return null; + } catch (JSONException e) { + Log.e(Constants.TAG, "json error parsing stream", e); + return null; + } + } + + private static String authToken; + + private static String getAuthToken() { + if (authToken != null) { + return authToken; + } + try { + String base64Encoded = + "NkloUG5XYll4QVNBb0F6SDJRYVV0SEQwSjpMMEdudWlPbmFwV2JTQ" + + "mJRdExJcXRwZVM1QlR0dmgwNmRtb01vS1FmSFFTOFV3SHVXbQ=="; // Step 2: Obtain a bearer token HttpPost httpPost = new HttpPost("https://api.twitter.com/oauth2/token"); @@ -64,28 +206,21 @@ public class TwitterResource extends LinkedCookieResource { httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); httpPost.setEntity(new StringEntity("grant_type=client_credentials")); JSONObject rawAuthorization = new JSONObject(getResponseBody(httpPost)); - String auth = JWalk.getString(rawAuthorization, "access_token"); // Applications should verify that the value associated with the // token_type key of the returned object is bearer - if (auth != null && JWalk.getString(rawAuthorization, "token_type").equals("bearer")) { - - // Step 3: Authenticate API requests with bearer token - HttpGet httpGet = - new HttpGet("https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=" + screenName); - - // construct a normal HTTPS request and include an Authorization - // header with the value of Bearer <> - httpGet.setHeader("Authorization", "Bearer " + auth); - httpGet.setHeader("Content-Type", "application/json"); - // update the results with the body of the response - results = getResponseBody(httpGet); + if (!"bearer".equals(JWalk.getString(rawAuthorization, "token_type"))) { + return null; } - } catch (UnsupportedEncodingException ex) { - } catch (JSONException ex) { - } catch (IllegalStateException ex1) { + + authToken = JWalk.getString(rawAuthorization, "access_token"); + return authToken; + + } catch (UnsupportedEncodingException | JSONException | IllegalStateException ex) { + Log.e(Constants.TAG, "auth token fetching error", ex); + return null; } - return results; + } private static String getResponseBody(HttpRequestBase request) { @@ -104,41 +239,17 @@ public class TwitterResource extends LinkedCookieResource { BufferedReader bReader = new BufferedReader( new InputStreamReader(inputStream, "UTF-8"), 8); - String line = null; + String line; while ((line = bReader.readLine()) != null) { sb.append(line); } } else { sb.append(reason); } - } catch (UnsupportedEncodingException ex) { - } catch (ClientProtocolException ex1) { - } catch (IOException ex2) { + } catch (IOException e) { + Log.e(Constants.TAG, "http request error", e); } return sb.toString(); } - @Override - protected String fetchResource(OperationLog log, int indent) { - return getTwitterStream("Valodim"); - } - - @Override - public @DrawableRes int getDisplayIcon() { - return R.drawable.twitter; - } - - @Override - public String getDisplayTitle(Context context) { - return "twitter"; - } - - @Override - public String getDisplayComment(Context context) { - return null; - } - - public static LinkedCookieResource create(Set<String> flags, HashMap<String, String> params, URI subUri) { - return null; - } } |