support github resource (pa)
This commit is contained in:
@@ -777,6 +777,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_LV_FETCH_ERROR (LogLevel.ERROR, R.string.msg_lv_fetch_error),
|
MSG_LV_FETCH_ERROR (LogLevel.ERROR, R.string.msg_lv_fetch_error),
|
||||||
MSG_LV_FETCH_ERROR_URL (LogLevel.ERROR, R.string.msg_lv_fetch_error_url),
|
MSG_LV_FETCH_ERROR_URL (LogLevel.ERROR, R.string.msg_lv_fetch_error_url),
|
||||||
MSG_LV_FETCH_ERROR_IO (LogLevel.ERROR, R.string.msg_lv_fetch_error_io),
|
MSG_LV_FETCH_ERROR_IO (LogLevel.ERROR, R.string.msg_lv_fetch_error_io),
|
||||||
|
MSG_LV_FETCH_ERROR_FORMAT(LogLevel.ERROR, R.string.msg_lv_fetch_error_format),
|
||||||
|
|
||||||
//export log
|
//export log
|
||||||
MSG_EXPORT_LOG(LogLevel.START,R.string.msg_export_log_start),
|
MSG_EXPORT_LOG(LogLevel.START,R.string.msg_export_log_start),
|
||||||
|
|||||||
@@ -2,6 +2,12 @@ package org.sufficientlysecure.keychain.pgp.linked;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.apache.http.client.methods.HttpRequestBase;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.apache.http.params.BasicHttpParams;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
|
import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||||
@@ -9,6 +15,10 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat
|
|||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -117,4 +127,49 @@ public abstract class LinkedCookieResource extends LinkedResource {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getResponseBody(HttpRequestBase request) throws IOException, HttpStatusException {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
DefaultHttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());
|
||||||
|
HttpResponse response = httpClient.execute(request);
|
||||||
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
|
String reason = response.getStatusLine().getReasonPhrase();
|
||||||
|
|
||||||
|
if (statusCode != 200) {
|
||||||
|
throw new HttpStatusException(statusCode, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
InputStream inputStream = entity.getContent();
|
||||||
|
|
||||||
|
BufferedReader bReader = new BufferedReader(
|
||||||
|
new InputStreamReader(inputStream, "UTF-8"), 8);
|
||||||
|
String line;
|
||||||
|
while ((line = bReader.readLine()) != null) {
|
||||||
|
sb.append(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HttpStatusException extends Throwable {
|
||||||
|
|
||||||
|
private final int mStatusCode;
|
||||||
|
private final String mReason;
|
||||||
|
|
||||||
|
HttpStatusException(int statusCode, String reason) {
|
||||||
|
mStatusCode = statusCode;
|
||||||
|
mReason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatus() {
|
||||||
|
return mStatusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReason() {
|
||||||
|
return mReason;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
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.support.annotation.StringRes;
|
||||||
|
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
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.LogType;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.linked.LinkedCookieResource;
|
||||||
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
||||||
|
public class GithubResource extends LinkedCookieResource {
|
||||||
|
|
||||||
|
final String mHandle;
|
||||||
|
final String mGistId;
|
||||||
|
|
||||||
|
GithubResource(Set<String> flags, HashMap<String,String> params, URI uri,
|
||||||
|
String handle, String gistId) {
|
||||||
|
super(flags, params, uri);
|
||||||
|
|
||||||
|
mHandle = handle;
|
||||||
|
mGistId = gistId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateText (Context context, byte[] fingerprint) {
|
||||||
|
String cookie = LinkedCookieResource.generate(context, fingerprint);
|
||||||
|
|
||||||
|
return String.format(context.getResources().getString(R.string.linked_id_github_text), cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String fetchResource (OperationLog log, int indent) {
|
||||||
|
|
||||||
|
log.add(LogType.MSG_LV_FETCH, indent, mSubUri.toString());
|
||||||
|
indent += 1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
HttpGet httpGet = new HttpGet("https://api.github.com/gists/" + mGistId);
|
||||||
|
|
||||||
|
String response = getResponseBody(httpGet);
|
||||||
|
|
||||||
|
JSONObject obj = new JSONObject(response);
|
||||||
|
|
||||||
|
JSONObject owner = obj.getJSONObject("owner");
|
||||||
|
if (!mHandle.equals(owner.getString("login"))) {
|
||||||
|
log.add(LogType.MSG_LV_FETCH_ERROR_FORMAT, indent);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject files = obj.getJSONObject("files");
|
||||||
|
Iterator<String> it = files.keys();
|
||||||
|
if (it.hasNext()) {
|
||||||
|
// TODO can there be multiple candidates?
|
||||||
|
JSONObject file = files.getJSONObject(it.next());
|
||||||
|
return file.getString("content");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (HttpStatusException e) {
|
||||||
|
// log verbose output to logcat
|
||||||
|
Log.e(Constants.TAG, "http error (" + e.getStatus() + "): " + e.getReason());
|
||||||
|
log.add(LogType.MSG_LV_FETCH_ERROR, indent, Integer.toString(e.getStatus()));
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
log.add(LogType.MSG_LV_FETCH_ERROR_URL, indent);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(Constants.TAG, "io error", e);
|
||||||
|
log.add(LogType.MSG_LV_FETCH_ERROR_IO, indent);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(Constants.TAG, "json error", e);
|
||||||
|
log.add(LogType.MSG_LV_FETCH_ERROR_FORMAT, indent);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GithubResource 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://gist\\.github\\.com/([a-zA-Z0-9_]+)/([0-9a-f]+)");
|
||||||
|
Matcher match = p.matcher(uri.toString());
|
||||||
|
if (!match.matches()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String handle = match.group(1);
|
||||||
|
String gistId = match.group(2);
|
||||||
|
|
||||||
|
return new GithubResource(flags, params, uri, handle, gistId);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @DrawableRes
|
||||||
|
int getDisplayIcon() {
|
||||||
|
return R.drawable.github;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @StringRes
|
||||||
|
int getVerifiedText() {
|
||||||
|
return R.string.linked_verified_github;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayTitle(Context context) {
|
||||||
|
return "Github";
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,27 +9,19 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.textuality.keybase.lib.JWalk;
|
import com.textuality.keybase.lib.JWalk;
|
||||||
|
|
||||||
import org.apache.http.HttpEntity;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.client.methods.HttpRequestBase;
|
|
||||||
import org.apache.http.entity.StringEntity;
|
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.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||||
import org.sufficientlysecure.keychain.pgp.linked.LinkedCookieResource;
|
import org.sufficientlysecure.keychain.pgp.linked.LinkedCookieResource;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -61,7 +53,7 @@ public class TwitterResource extends LinkedCookieResource {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern p = Pattern.compile("https://twitter.com/([a-zA-Z0-9_]+)/status/([0-9]+)");
|
Pattern p = Pattern.compile("https://twitter\\.com/([a-zA-Z0-9_]+)/status/([0-9]+)");
|
||||||
Matcher match = p.matcher(uri.toString());
|
Matcher match = p.matcher(uri.toString());
|
||||||
if (!match.matches()) {
|
if (!match.matches()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -102,16 +94,25 @@ public class TwitterResource extends LinkedCookieResource {
|
|||||||
|
|
||||||
JSONObject user = obj.getJSONObject("user");
|
JSONObject user = obj.getJSONObject("user");
|
||||||
if (!mHandle.equalsIgnoreCase(user.getString("screen_name"))) {
|
if (!mHandle.equalsIgnoreCase(user.getString("screen_name"))) {
|
||||||
|
log.add(LogType.MSG_LV_FETCH_ERROR_FORMAT, indent);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the results with the body of the response
|
// update the results with the body of the response
|
||||||
return obj.getString("text");
|
return obj.getString("text");
|
||||||
|
} catch (HttpStatusException e) {
|
||||||
|
// log verbose output to logcat
|
||||||
|
Log.e(Constants.TAG, "http error (" + e.getStatus() + "): " + e.getReason());
|
||||||
|
log.add(LogType.MSG_LV_FETCH_ERROR, indent, Integer.toString(e.getStatus()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(Constants.TAG, "io error", e);
|
||||||
|
log.add(LogType.MSG_LV_FETCH_ERROR_IO, indent);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
Log.e(Constants.TAG, "json error parsing stream", e);
|
Log.e(Constants.TAG, "json error", e);
|
||||||
return null;
|
log.add(LogType.MSG_LV_FETCH_ERROR_FORMAT, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -184,10 +185,11 @@ public class TwitterResource extends LinkedCookieResource {
|
|||||||
|
|
||||||
// update the results with the body of the response
|
// update the results with the body of the response
|
||||||
return null;
|
return null;
|
||||||
} catch (JSONException e) {
|
} catch (JSONException | HttpStatusException | IOException e) {
|
||||||
Log.e(Constants.TAG, "json error parsing stream", e);
|
Log.e(Constants.TAG, "exception parsing stream", e);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String authToken;
|
private static String authToken;
|
||||||
@@ -217,42 +219,13 @@ public class TwitterResource extends LinkedCookieResource {
|
|||||||
authToken = JWalk.getString(rawAuthorization, "access_token");
|
authToken = JWalk.getString(rawAuthorization, "access_token");
|
||||||
return authToken;
|
return authToken;
|
||||||
|
|
||||||
} catch (UnsupportedEncodingException | JSONException | IllegalStateException ex) {
|
} catch (JSONException | IllegalStateException | HttpStatusException | IOException ex) {
|
||||||
Log.e(Constants.TAG, "auth token fetching error", ex);
|
Log.e(Constants.TAG, "exception fetching auth token", ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getResponseBody(HttpRequestBase request) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
try {
|
|
||||||
|
|
||||||
DefaultHttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());
|
|
||||||
HttpResponse response = httpClient.execute(request);
|
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
|
||||||
String reason = response.getStatusLine().getReasonPhrase();
|
|
||||||
|
|
||||||
if (statusCode == 200) {
|
|
||||||
|
|
||||||
HttpEntity entity = response.getEntity();
|
|
||||||
InputStream inputStream = entity.getContent();
|
|
||||||
|
|
||||||
BufferedReader bReader = new BufferedReader(
|
|
||||||
new InputStreamReader(inputStream, "UTF-8"), 8);
|
|
||||||
String line;
|
|
||||||
while ((line = bReader.readLine()) != null) {
|
|
||||||
sb.append(line);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sb.append(reason);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(Constants.TAG, "http request error", e);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String rot13(String input) {
|
public static String rot13(String input) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (int i = 0; i < input.length(); i++) {
|
for (int i = 0; i < input.length(); i++) {
|
||||||
|
|||||||
BIN
OpenKeychain/src/main/res/drawable/github.png
Normal file
BIN
OpenKeychain/src/main/res/drawable/github.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
@@ -1178,6 +1178,7 @@
|
|||||||
<string name="msg_lv_fetch_error">"Server error (HTTP %s)"</string>
|
<string name="msg_lv_fetch_error">"Server error (HTTP %s)"</string>
|
||||||
<string name="msg_lv_fetch_error_url">"URL is malformed!"</string>
|
<string name="msg_lv_fetch_error_url">"URL is malformed!"</string>
|
||||||
<string name="msg_lv_fetch_error_io">"IO Error!"</string>
|
<string name="msg_lv_fetch_error_io">"IO Error!"</string>
|
||||||
|
<string name="msg_lv_fetch_error_format">"Format error!"</string>
|
||||||
|
|
||||||
<string name="msg_acc_saved">"Account saved"</string>
|
<string name="msg_acc_saved">"Account saved"</string>
|
||||||
|
|
||||||
@@ -1307,6 +1308,7 @@
|
|||||||
<string name="linked_create_verify">"Verify"</string>
|
<string name="linked_create_verify">"Verify"</string>
|
||||||
<string name="linked_text_clipboard">Text has been copied to clipboard</string>
|
<string name="linked_text_clipboard">Text has been copied to clipboard</string>
|
||||||
<string name="linked_verified_https">"The Website has been fetched and verified."</string>
|
<string name="linked_verified_https">"The Website has been fetched and verified."</string>
|
||||||
|
<string name="linked_verified_github">"The Gist has been fetched and verified."</string>
|
||||||
<string name="linked_verified_dns">"The DNS record has been fetched and verified."</string>
|
<string name="linked_verified_dns">"The DNS record has been fetched and verified."</string>
|
||||||
<string name="linked_verified_twitter">"The Tweet has been fetched and verified."</string>
|
<string name="linked_verified_twitter">"The Tweet has been fetched and verified."</string>
|
||||||
<plurals name="linked_id_expand">
|
<plurals name="linked_id_expand">
|
||||||
@@ -1317,6 +1319,7 @@
|
|||||||
<string name="linked_select_1">"A \'linked identity\' connects your pgp key to a resource on the web."</string>
|
<string name="linked_select_1">"A \'linked identity\' connects your pgp key to a resource on the web."</string>
|
||||||
<string name="linked_select_2">"Please select a type:"</string>
|
<string name="linked_select_2">"Please select a type:"</string>
|
||||||
<string name="linked_id_generic_text">"This file claims ownership of the OpenPGP key with long id %2$s.\n\nCookie for proof:\n%1$s"</string>
|
<string name="linked_id_generic_text">"This file claims ownership of the OpenPGP key with long id %2$s.\n\nCookie for proof:\n%1$s"</string>
|
||||||
|
<string name="linked_id_github_text">"This Gist confirms the Linked Identity in my OpenPGP key, and links it to this Github account.\n\nCookie for proof:\n%1$s"</string>
|
||||||
<string name="linked_verifying">"Verifying…"</string>
|
<string name="linked_verifying">"Verifying…"</string>
|
||||||
<string name="linked_verify_success">"Verified!"</string>
|
<string name="linked_verify_success">"Verified!"</string>
|
||||||
<string name="linked_verify_error">"Verification error!"</string>
|
<string name="linked_verify_error">"Verification error!"</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user