mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-01-31 08:54:57 +01:00
improved oauth browser sign in
This commit is contained in:
parent
25714f06b9
commit
af2ff44328
@ -45,4 +45,8 @@ public interface TwitterOAuth {
|
||||
OAuthToken getAccessToken(@Extra({"oauth_token", "oauth_token_secret"}) OAuthToken requestToken,
|
||||
@Param("oauth_verifier") String oauthVerifier) throws TwitterException;
|
||||
|
||||
@POST("/oauth/access_token")
|
||||
OAuthToken getAccessToken(@Extra({"oauth_token", "oauth_token_secret"}) OAuthToken requestToken)
|
||||
throws TwitterException;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mariotaku.twidere.util.UriUtils;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/2/9.
|
||||
*/
|
||||
public class UriUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testGetAuthority() throws Exception {
|
||||
assertEquals("www.google.com", UriUtils.getAuthority("http://www.google.com/"));
|
||||
assertEquals("twitter.com", UriUtils.getAuthority("https://twitter.com"));
|
||||
assertNull(UriUtils.getAuthority("www.google.com/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPath() throws Exception {
|
||||
assertEquals("/", UriUtils.getPath("http://www.example.com/"));
|
||||
assertEquals("", UriUtils.getPath("http://www.example.com"));
|
||||
assertEquals("/test/path", UriUtils.getPath("https://example.com/test/path"));
|
||||
assertEquals("/test/path", UriUtils.getPath("https://example.com/test/path?with=query"));
|
||||
assertEquals("/test/path/", UriUtils.getPath("https://example.com/test/path/?with=query"));
|
||||
assertEquals("/test/path", UriUtils.getPath("https://example.com/test/path?with=query#fragment"));
|
||||
assertEquals("/test/path/", UriUtils.getPath("https://example.com/test/path/?with=query#fragment"));
|
||||
assertEquals("/test/path", UriUtils.getPath("https://example.com/test/path#fragment"));
|
||||
assertEquals("/test/path/", UriUtils.getPath("https://example.com/test/path/#fragment"));
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package org.mariotaku.twidere.util.media.preview;
|
||||
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/2/9.
|
||||
*/
|
||||
public class PreviewMediaExtractorTest {
|
||||
|
||||
@Test
|
||||
public void testGetAuthority() throws Exception {
|
||||
assertEquals("www.google.com", PreviewMediaExtractor.getAuthority("http://www.google.com/"));
|
||||
assertEquals("twitter.com", PreviewMediaExtractor.getAuthority("https://twitter.com"));
|
||||
assertNull(PreviewMediaExtractor.getAuthority("www.google.com/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPath() throws Exception {
|
||||
assertEquals("/", PreviewMediaExtractor.getPath("http://www.example.com/"));
|
||||
assertEquals("", PreviewMediaExtractor.getPath("http://www.example.com"));
|
||||
assertEquals("/test/path", PreviewMediaExtractor.getPath("https://example.com/test/path"));
|
||||
assertEquals("/test/path", PreviewMediaExtractor.getPath("https://example.com/test/path?with=query"));
|
||||
assertEquals("/test/path/", PreviewMediaExtractor.getPath("https://example.com/test/path/?with=query"));
|
||||
assertEquals("/test/path", PreviewMediaExtractor.getPath("https://example.com/test/path?with=query#fragment"));
|
||||
assertEquals("/test/path/", PreviewMediaExtractor.getPath("https://example.com/test/path/?with=query#fragment"));
|
||||
assertEquals("/test/path", PreviewMediaExtractor.getPath("https://example.com/test/path#fragment"));
|
||||
assertEquals("/test/path/", PreviewMediaExtractor.getPath("https://example.com/test/path/#fragment"));
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@ package org.mariotaku.twidere.activity.support;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
@ -30,7 +29,6 @@ import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
@ -38,12 +36,11 @@ import android.widget.Toast;
|
||||
|
||||
import org.attoparser.AttoParseException;
|
||||
import org.mariotaku.restfu.http.Authorization;
|
||||
import org.mariotaku.restfu.http.Endpoint;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterOAuth;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthAuthorization;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthEndpoint;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthToken;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
import org.mariotaku.twidere.util.AsyncTaskUtils;
|
||||
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator;
|
||||
@ -52,9 +49,9 @@ import org.mariotaku.twidere.util.webkit.DefaultWebViewClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Set;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.mariotaku.twidere.util.Utils.getNonEmptyString;
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
public class BrowserSignInActivity extends BaseAppCompatActivity {
|
||||
@ -97,7 +94,6 @@ public class BrowserSignInActivity extends BaseAppCompatActivity {
|
||||
@SuppressLint("AddJavascriptInterface")
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_browser_sign_in);
|
||||
mWebView.setWebViewClient(new AuthorizationWebViewClient(this));
|
||||
@ -152,7 +148,25 @@ public class BrowserSignInActivity extends BaseAppCompatActivity {
|
||||
public void onPageFinished(final WebView view, final String url) {
|
||||
super.onPageFinished(view, url);
|
||||
view.loadUrl(INJECT_CONTENT);
|
||||
((BrowserSignInActivity) getActivity()).setLoadProgressShown(false);
|
||||
final BrowserSignInActivity activity = (BrowserSignInActivity) getActivity();
|
||||
activity.setLoadProgressShown(false);
|
||||
Uri uri = Uri.parse(url);
|
||||
// Hack for fanfou
|
||||
if ("fanfou.com".equals(uri.getHost())) {
|
||||
final String path = uri.getPath();
|
||||
final Set<String> paramNames = uri.getQueryParameterNames();
|
||||
if ("/oauth/authorize".equals(path) && paramNames.contains("oauth_callback")) {
|
||||
// Sign in successful response.
|
||||
final OAuthToken requestToken = activity.mRequestToken;
|
||||
if (requestToken != null) {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(EXTRA_REQUEST_TOKEN, requestToken.getOauthToken());
|
||||
intent.putExtra(EXTRA_REQUEST_TOKEN_SECRET, requestToken.getOauthTokenSecret());
|
||||
activity.setResult(RESULT_OK, intent);
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -167,7 +181,7 @@ public class BrowserSignInActivity extends BaseAppCompatActivity {
|
||||
final String failingUrl) {
|
||||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
final Activity activity = getActivity();
|
||||
Toast.makeText(activity, R.string.error_occurred, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(activity, description, Toast.LENGTH_SHORT).show();
|
||||
activity.finish();
|
||||
}
|
||||
|
||||
@ -196,36 +210,27 @@ public class BrowserSignInActivity extends BaseAppCompatActivity {
|
||||
static class GetRequestTokenTask extends AsyncTask<Object, Object, OAuthToken> {
|
||||
|
||||
private final String mConsumerKey, mConsumerSecret;
|
||||
private final TwidereApplication mApplication;
|
||||
private final SharedPreferences mPreferences;
|
||||
private final BrowserSignInActivity mActivity;
|
||||
private final String mAPIUrlFormat;
|
||||
|
||||
public GetRequestTokenTask(final BrowserSignInActivity activity) {
|
||||
mActivity = activity;
|
||||
mApplication = TwidereApplication.getInstance(activity);
|
||||
mPreferences = activity.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE);
|
||||
final Intent intent = activity.getIntent();
|
||||
mConsumerKey = intent.getStringExtra(Accounts.CONSUMER_KEY);
|
||||
mConsumerSecret = intent.getStringExtra(Accounts.CONSUMER_SECRET);
|
||||
mAPIUrlFormat = intent.getStringExtra(Accounts.API_URL_FORMAT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OAuthToken doInBackground(final Object... params) {
|
||||
final String defConsumerKey = getNonEmptyString(mPreferences, KEY_CONSUMER_KEY, TWITTER_CONSUMER_KEY);
|
||||
final String defConsumerSecret = getNonEmptyString(mPreferences, KEY_CONSUMER_SECRET,
|
||||
TWITTER_CONSUMER_SECRET);
|
||||
final String consumerKey, consumerSecret;
|
||||
if (!isEmpty(mConsumerKey) && !isEmpty(mConsumerSecret)) {
|
||||
consumerKey = mConsumerKey;
|
||||
consumerSecret = mConsumerSecret;
|
||||
} else {
|
||||
consumerKey = defConsumerKey;
|
||||
consumerSecret = defConsumerSecret;
|
||||
if (isEmpty(mConsumerKey) || isEmpty(mConsumerSecret)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
final OAuthEndpoint endpoint = new OAuthEndpoint(TwitterAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", null));
|
||||
final Authorization auth = new OAuthAuthorization(consumerKey, consumerSecret);
|
||||
final TwitterOAuth twitter = TwitterAPIFactory.getInstance(mActivity, endpoint, auth, TwitterOAuth.class);
|
||||
final Endpoint endpoint = TwitterAPIFactory.getOAuthSignInEndpoint(mAPIUrlFormat, true);
|
||||
final Authorization auth = new OAuthAuthorization(mConsumerKey, mConsumerSecret);
|
||||
final TwitterOAuth twitter = TwitterAPIFactory.getInstance(mActivity, endpoint,
|
||||
auth, TwitterOAuth.class);
|
||||
return twitter.getRequestToken(OAUTH_CALLBACK_OOB);
|
||||
} catch (final Exception e) {
|
||||
Log.w(LOGTAG, e);
|
||||
@ -244,7 +249,7 @@ public class BrowserSignInActivity extends BaseAppCompatActivity {
|
||||
}
|
||||
return;
|
||||
}
|
||||
final OAuthEndpoint endpoint = new OAuthEndpoint(TwitterAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", null));
|
||||
final Endpoint endpoint = TwitterAPIFactory.getOAuthSignInEndpoint(mAPIUrlFormat, true);
|
||||
mActivity.loadUrl(endpoint.construct("/oauth/authorize", new String[]{"oauth_token", data.getOauthToken()}));
|
||||
}
|
||||
|
||||
|
@ -267,6 +267,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
||||
final Intent intent = new Intent(this, BrowserSignInActivity.class);
|
||||
intent.putExtra(Accounts.CONSUMER_KEY, mConsumerKey);
|
||||
intent.putExtra(Accounts.CONSUMER_SECRET, mConsumerSecret);
|
||||
intent.putExtra(Accounts.API_URL_FORMAT, mAPIUrlFormat);
|
||||
startActivityForResult(intent, REQUEST_BROWSER_SIGN_IN);
|
||||
break;
|
||||
}
|
||||
@ -640,17 +641,20 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
||||
|
||||
public static class BrowserSignInTask extends AbstractSignInTask {
|
||||
|
||||
private final String oauthVerifier;
|
||||
|
||||
private final Context context;
|
||||
|
||||
@NonNull
|
||||
private final String apiUrlFormat;
|
||||
private final boolean sameOauthSigningUrl, noVersionSuffix;
|
||||
@Nullable
|
||||
private final String oauthVerifier;
|
||||
private final OAuthToken consumerKey, requestToken;
|
||||
private final boolean sameOauthSigningUrl, noVersionSuffix;
|
||||
|
||||
public BrowserSignInTask(final SignInActivity context, OAuthToken consumerKey,
|
||||
final OAuthToken requestToken,
|
||||
final String oauthVerifier, @NonNull final String apiUrlFormat,
|
||||
public BrowserSignInTask(@NonNull final SignInActivity context,
|
||||
@NonNull final OAuthToken consumerKey,
|
||||
@NonNull final OAuthToken requestToken,
|
||||
@Nullable final String oauthVerifier,
|
||||
@NonNull final String apiUrlFormat,
|
||||
final boolean sameOauthSigningUrl, final boolean noVersionSuffix) {
|
||||
super(context);
|
||||
this.context = context;
|
||||
@ -666,23 +670,26 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
||||
protected SignInResponse doInBackground(final Object... params) {
|
||||
try {
|
||||
final String versionSuffix = noVersionSuffix ? null : "1.1";
|
||||
Endpoint endpoint = TwitterAPIFactory.getOAuthEndpoint(apiUrlFormat, "api", null,
|
||||
Endpoint endpoint = TwitterAPIFactory.getOAuthSignInEndpoint(apiUrlFormat,
|
||||
sameOauthSigningUrl);
|
||||
final TwitterOAuth oauth = TwitterAPIFactory.getInstance(context, endpoint,
|
||||
new OAuthAuthorization(consumerKey.getOauthToken(),
|
||||
consumerKey.getOauthTokenSecret()), TwitterOAuth.class);
|
||||
final OAuthToken accessToken = oauth.getAccessToken(requestToken, oauthVerifier);
|
||||
final String userId = accessToken.getUserId();
|
||||
if (userId == null) return new SignInResponse(false, false, null);
|
||||
final OAuthToken accessToken;
|
||||
if (oauthVerifier != null) {
|
||||
accessToken = oauth.getAccessToken(requestToken, oauthVerifier);
|
||||
} else {
|
||||
accessToken = oauth.getAccessToken(requestToken);
|
||||
}
|
||||
final OAuthAuthorization auth = new OAuthAuthorization(consumerKey.getOauthToken(),
|
||||
consumerKey.getOauthTokenSecret(), accessToken);
|
||||
endpoint = TwitterAPIFactory.getOAuthEndpoint(apiUrlFormat, "api", versionSuffix,
|
||||
sameOauthSigningUrl);
|
||||
final Twitter twitter = TwitterAPIFactory.getInstance(context, endpoint,
|
||||
auth, Twitter.class);
|
||||
final Twitter twitter = TwitterAPIFactory.getInstance(context, endpoint, auth,
|
||||
Twitter.class);
|
||||
final User user = twitter.verifyCredentials();
|
||||
final int color = analyseUserProfileColor(user);
|
||||
return new SignInResponse(isUserLoggedIn(context, userId), auth, user,
|
||||
return new SignInResponse(isUserLoggedIn(context, user.getId()), auth, user,
|
||||
ParcelableCredentials.AUTH_TYPE_OAUTH, color, apiUrlFormat, sameOauthSigningUrl,
|
||||
noVersionSuffix, detectAccountType(twitter, user));
|
||||
} catch (final TwitterException e) {
|
||||
@ -759,7 +766,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
||||
private SignInResponse authOAuth() throws AuthenticationException, TwitterException {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity == null) return new SignInResponse(false, false, null);
|
||||
Endpoint endpoint = TwitterAPIFactory.getOAuthEndpoint(apiUrlFormat, "api", null, sameOAuthSigningUrl);
|
||||
Endpoint endpoint = TwitterAPIFactory.getOAuthSignInEndpoint(apiUrlFormat,
|
||||
sameOAuthSigningUrl);
|
||||
OAuthAuthorization auth = new OAuthAuthorization(consumerKey.getOauthToken(), consumerKey.getOauthTokenSecret());
|
||||
final TwitterOAuth oauth = TwitterAPIFactory.getInstance(activity, endpoint, auth, TwitterOAuth.class);
|
||||
final OAuthPasswordAuthenticator authenticator = new OAuthPasswordAuthenticator(oauth, verificationCallback, userAgent);
|
||||
@ -773,7 +781,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
||||
private SignInResponse authxAuth() throws TwitterException {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity == null) return new SignInResponse(false, false, null);
|
||||
Endpoint endpoint = TwitterAPIFactory.getOAuthEndpoint(apiUrlFormat, "api", null, sameOAuthSigningUrl);
|
||||
Endpoint endpoint = TwitterAPIFactory.getOAuthSignInEndpoint(apiUrlFormat,
|
||||
sameOAuthSigningUrl);
|
||||
OAuthAuthorization auth = new OAuthAuthorization(consumerKey.getOauthToken(), consumerKey.getOauthTokenSecret());
|
||||
final TwitterOAuth oauth = TwitterAPIFactory.getInstance(activity, endpoint, auth, TwitterOAuth.class);
|
||||
final OAuthToken accessToken = oauth.getAccessToken(username, password);
|
||||
@ -963,6 +972,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
||||
final AlertDialog alertDialog = (AlertDialog) dialog;
|
||||
final TextView verificationHint = (TextView) alertDialog.findViewById(R.id.verification_hint);
|
||||
final EditText editVerification = (EditText) alertDialog.findViewById(R.id.edit_verification_code);
|
||||
if (verificationHint == null || editVerification == null) return;
|
||||
if ("Push".equalsIgnoreCase(challengeType)) {
|
||||
verificationHint.setText(R.string.login_verification_push_hint);
|
||||
editVerification.setVisibility(View.GONE);
|
||||
|
@ -11,7 +11,7 @@ import org.mariotaku.twidere.api.twitter.model.User;
|
||||
import org.mariotaku.twidere.model.UserKey;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor;
|
||||
import org.mariotaku.twidere.util.UriUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -86,7 +86,7 @@ public class UserKeyUtils {
|
||||
def = TwidereConstants.USER_TYPE_TWITTER_COM;
|
||||
}
|
||||
if (uri == null) return def;
|
||||
final String authority = PreviewMediaExtractor.getAuthority(uri);
|
||||
final String authority = UriUtils.getAuthority(uri);
|
||||
if (authority == null) return def;
|
||||
return authority.replaceAll("[^\\w\\d\\.]", "-");
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import org.mariotaku.twidere.api.twitter.model.User;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.UserKey;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
|
||||
import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -160,7 +159,7 @@ public class InternalTwitterContentUtils {
|
||||
public static String getBestBannerUrl(@Nullable final String baseUrl, final int width) {
|
||||
if (baseUrl == null) return null;
|
||||
final String type = getBestBannerType(width);
|
||||
final String authority = PreviewMediaExtractor.getAuthority(baseUrl);
|
||||
final String authority = UriUtils.getAuthority(baseUrl);
|
||||
return authority != null && authority.endsWith(".twimg.com") ? baseUrl + "/" + type : baseUrl;
|
||||
}
|
||||
|
||||
|
@ -335,7 +335,7 @@ public class TwitterAPIFactory implements TwidereConstants {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String getApiUrl(final String pattern, final String domain, String appendPath) {
|
||||
public static String getApiUrl(@NonNull final String pattern, final String domain, String appendPath) {
|
||||
String urlBase = getApiBaseUrl(pattern, domain);
|
||||
if (urlBase.endsWith("/")) {
|
||||
urlBase = urlBase.substring(0, urlBase.length() - 1);
|
||||
@ -390,14 +390,33 @@ public class TwitterAPIFactory implements TwidereConstants {
|
||||
}
|
||||
}
|
||||
|
||||
public static Endpoint getOAuthRestEndpoint(String apiUrlFormat, boolean sameOAuthSigningUrl, boolean noVersionSuffix) {
|
||||
public static Endpoint getOAuthRestEndpoint(@NonNull String apiUrlFormat, boolean sameOAuthSigningUrl, boolean noVersionSuffix) {
|
||||
return getOAuthEndpoint(apiUrlFormat, "api", noVersionSuffix ? null : "1.1", sameOAuthSigningUrl);
|
||||
}
|
||||
|
||||
public static Endpoint getOAuthSignInEndpoint(@NonNull String apiUrlFormat, boolean sameOAuthSigningUrl) {
|
||||
return getOAuthEndpoint(apiUrlFormat, "api", null, sameOAuthSigningUrl, true);
|
||||
}
|
||||
|
||||
public static Endpoint getOAuthEndpoint(String apiUrlFormat, @Nullable String domain,
|
||||
@Nullable String versionSuffix, boolean sameOAuthSigningUrl) {
|
||||
@Nullable String versionSuffix,
|
||||
boolean sameOAuthSigningUrl) {
|
||||
return getOAuthEndpoint(apiUrlFormat, domain, versionSuffix, sameOAuthSigningUrl, false);
|
||||
}
|
||||
|
||||
public static Endpoint getOAuthEndpoint(@NonNull String apiUrlFormat, @Nullable String domain,
|
||||
@Nullable String versionSuffix,
|
||||
boolean sameOAuthSigningUrl, boolean fixUrl) {
|
||||
String endpointUrl, signEndpointUrl;
|
||||
endpointUrl = getApiUrl(apiUrlFormat, domain, versionSuffix);
|
||||
if (fixUrl) {
|
||||
int[] authorityRange = UriUtils.getAuthorityRange(endpointUrl);
|
||||
if (authorityRange != null && endpointUrl.regionMatches(authorityRange[0],
|
||||
"api.fanfou.com", 0, authorityRange[1] - authorityRange[0])) {
|
||||
endpointUrl = endpointUrl.substring(0, authorityRange[0]) + "fanfou.com" +
|
||||
endpointUrl.substring(authorityRange[1]);
|
||||
}
|
||||
}
|
||||
if (!sameOAuthSigningUrl) {
|
||||
signEndpointUrl = getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, domain, versionSuffix);
|
||||
} else {
|
||||
|
@ -20,6 +20,8 @@
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/3/23.
|
||||
@ -39,4 +41,45 @@ public class UriUtils {
|
||||
public static Uri appendQueryParameters(Uri uri, String key, boolean value) {
|
||||
return appendQueryParameters(uri, key, ParseUtils.parseString(value));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getAuthority(@NonNull String link) {
|
||||
int start = link.indexOf("://");
|
||||
if (start < 0) return null;
|
||||
int end = link.indexOf('/', start + 3);
|
||||
if (end < 0) {
|
||||
end = link.length();
|
||||
}
|
||||
return link.substring(start + 3, end);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static int[] getAuthorityRange(@NonNull String link) {
|
||||
int start = link.indexOf("://");
|
||||
if (start < 0) return null;
|
||||
int end = link.indexOf('/', start + 3);
|
||||
if (end < 0) {
|
||||
end = link.length();
|
||||
}
|
||||
return new int[]{start + 3, end};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getPath(@NonNull String link) {
|
||||
int start = link.indexOf("://");
|
||||
if (start < 0) return null;
|
||||
start = link.indexOf('/', start + 3);
|
||||
if (start < 0) {
|
||||
return "";
|
||||
}
|
||||
int end = link.indexOf('?', start);
|
||||
if (end < 0) {
|
||||
end = link.indexOf('#', start);
|
||||
if (end < 0) {
|
||||
end = link.length();
|
||||
}
|
||||
}
|
||||
return link.substring(start, end);
|
||||
}
|
||||
}
|
||||
|
@ -71,32 +71,4 @@ public class PreviewMediaExtractor {
|
||||
return links;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getAuthority(@NonNull String link) {
|
||||
int start = link.indexOf("://");
|
||||
if (start < 0) return null;
|
||||
int end = link.indexOf('/', start + 3);
|
||||
if (end < 0) {
|
||||
end = link.length();
|
||||
}
|
||||
return link.substring(start + 3, end);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getPath(@NonNull String link) {
|
||||
int start = link.indexOf("://");
|
||||
if (start < 0) return null;
|
||||
start = link.indexOf('/', start + 3);
|
||||
if (start < 0) {
|
||||
return "";
|
||||
}
|
||||
int end = link.indexOf('?', start);
|
||||
if (end < 0) {
|
||||
end = link.indexOf('#', start);
|
||||
if (end < 0) {
|
||||
end = link.length();
|
||||
}
|
||||
}
|
||||
return link.substring(start, end);
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import android.support.annotation.WorkerThread;
|
||||
|
||||
import org.mariotaku.restfu.http.RestHttpClient;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor;
|
||||
import org.mariotaku.twidere.util.UriUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@ -16,14 +16,14 @@ import java.util.Locale;
|
||||
public class InstagramProvider implements Provider {
|
||||
@Override
|
||||
public boolean supports(@NonNull String link) {
|
||||
final String authority = PreviewMediaExtractor.getAuthority(link);
|
||||
final String authority = UriUtils.getAuthority(link);
|
||||
if (authority == null) return false;
|
||||
switch (authority) {
|
||||
//noinspection SpellCheckingInspection
|
||||
case "instagr.am":
|
||||
case "instagram.com":
|
||||
case "www.instagram.com": {
|
||||
final String path = PreviewMediaExtractor.getPath(link);
|
||||
final String path = UriUtils.getPath(link);
|
||||
return path != null && path.startsWith("/p/");
|
||||
}
|
||||
}
|
||||
@ -33,7 +33,7 @@ public class InstagramProvider implements Provider {
|
||||
@Override
|
||||
@Nullable
|
||||
public ParcelableMedia from(@NonNull String link) {
|
||||
final String path = PreviewMediaExtractor.getPath(link);
|
||||
final String path = UriUtils.getPath(link);
|
||||
final String prefix = "/p/";
|
||||
if (path == null || !path.startsWith(prefix)) {
|
||||
return null;
|
@ -5,7 +5,7 @@ import android.support.annotation.Nullable;
|
||||
|
||||
import org.mariotaku.restfu.http.RestHttpClient;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor;
|
||||
import org.mariotaku.twidere.util.UriUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@ -21,7 +21,7 @@ public class TwitterMediaProvider implements Provider {
|
||||
@Nullable
|
||||
@Override
|
||||
public ParcelableMedia from(@NonNull String link) {
|
||||
final String path = PreviewMediaExtractor.getPath(link);
|
||||
final String path = UriUtils.getPath(link);
|
||||
if (path == null) return null;
|
||||
final ParcelableMedia media = new ParcelableMedia();
|
||||
media.url = link;
|
||||
@ -47,11 +47,11 @@ public class TwitterMediaProvider implements Provider {
|
||||
}
|
||||
|
||||
public static boolean isSupported(@NonNull String link) {
|
||||
final String authority = PreviewMediaExtractor.getAuthority(link);
|
||||
final String authority = UriUtils.getAuthority(link);
|
||||
if (authority == null || !authority.endsWith(".twimg.com")) {
|
||||
return false;
|
||||
}
|
||||
final String path = PreviewMediaExtractor.getPath(link);
|
||||
final String path = UriUtils.getPath(link);
|
||||
if (path == null) return false;
|
||||
if (path.startsWith("/media/")) {
|
||||
return true;
|
@ -107,6 +107,11 @@ public class ActivityTitleSummaryViewHolder extends ViewHolder implements View.O
|
||||
summaryView.setText(message.getSummary());
|
||||
summaryView.setVisibility(summaryView.length() > 0 ? View.VISIBLE : View.GONE);
|
||||
timeView.setTime(activity.timestamp);
|
||||
if (adapter.shouldShowAccountsColor()) {
|
||||
itemContent.drawEnd(activity.account_color);
|
||||
} else {
|
||||
itemContent.drawEnd();
|
||||
}
|
||||
displayUserProfileImages(sources);
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,15 @@
|
||||
<org.mariotaku.twidere.view.ColorLabelFrameLayout
|
||||
android:id="@+id/item_content"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="false"
|
||||
android:paddingLeft="@dimen/element_spacing_normal"
|
||||
android:paddingRight="@dimen/element_spacing_normal">
|
||||
android:paddingRight="@dimen/element_spacing_normal"
|
||||
app:ignorePadding="true">
|
||||
|
||||
<include layout="@layout/card_item_activity_summary_common"/>
|
||||
</org.mariotaku.twidere.view.ColorLabelFrameLayout>
|
@ -2,11 +2,13 @@
|
||||
<org.mariotaku.twidere.view.ColorLabelFrameLayout
|
||||
android:id="@+id/item_content"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="false">
|
||||
android:focusableInTouchMode="false"
|
||||
app:ignorePadding="true">
|
||||
|
||||
<include layout="@layout/card_item_activity_summary_common"/>
|
||||
</org.mariotaku.twidere.view.ColorLabelFrameLayout>
|
Loading…
x
Reference in New Issue
Block a user