Skip to content

Commit

Permalink
Add support for opaque shared URLs, fixes #1122 (#1123)
Browse files Browse the repository at this point in the history
  • Loading branch information
lol768 authored Oct 7, 2023
1 parent 8972921 commit 614e50a
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.quantumbadger.redreader.cache.CacheRequest;
import org.quantumbadger.redreader.fragments.ShareOrderDialog;
import org.quantumbadger.redreader.fragments.UserProfileDialog;
import org.quantumbadger.redreader.http.HTTPBackend;
import org.quantumbadger.redreader.image.AlbumInfo;
import org.quantumbadger.redreader.image.DeviantArtAPI;
import org.quantumbadger.redreader.image.GetAlbumInfoListener;
Expand All @@ -63,6 +64,7 @@
import org.quantumbadger.redreader.reddit.kthings.RedditPost;
import org.quantumbadger.redreader.reddit.url.ComposeMessageURL;
import org.quantumbadger.redreader.reddit.url.PostCommentListingURL;
import org.quantumbadger.redreader.reddit.url.OpaqueSharedURL;
import org.quantumbadger.redreader.reddit.url.RedditURLParser;

import java.util.ArrayList;
Expand Down Expand Up @@ -227,7 +229,26 @@ public static void onLinkClicked(
if(redditURL != null) {

switch(redditURL.pathType()) {

case RedditURLParser.OPAQUE_SHARED_URL:
// kick off a thread to get the real url
new Thread(() -> {
final String toFetchUrl = OpaqueSharedURL.getUrlToFetch(
(OpaqueSharedURL) redditURL
).toString();
final String realUrl = HTTPBackend.getBackend()
.resolveRedirectUri(toFetchUrl);
if(realUrl != null) {
activity.runOnUiThread(() -> onLinkClicked(
activity,
realUrl,
forceNoImage,
post,
albumInfo,
albumImageIndex,
fromExternalIntent));
}
}).start();
return;
case RedditURLParser.SUBREDDIT_POST_LISTING_URL:
case RedditURLParser.MULTIREDDIT_POST_LISTING_URL:
case RedditURLParser.USER_POST_LISTING_URL:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ public void onRequestSuccess(
case RedditURLParser.USER_COMMENT_LISTING_URL:
case RedditURLParser.USER_PROFILE_URL:
case RedditURLParser.COMPOSE_MESSAGE_URL:
case RedditURLParser.OPAQUE_SHARED_URL:
BugReportActivity.handleGlobalError(getActivity(), new RuntimeException(
"Unknown url type "
+ mPostListingURL.pathType()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
package org.quantumbadger.redreader.http;

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.quantumbadger.redreader.cache.CacheRequest;
import org.quantumbadger.redreader.common.Optional;
import org.quantumbadger.redreader.http.body.HTTPRequestBody;
Expand Down Expand Up @@ -87,6 +89,8 @@ void onError(
void onSuccess(String mimetype, Long bodyBytes, InputStream body);
}

public abstract @Nullable String resolveRedirectUri(String url);

public abstract Request prepareRequest(Context context, RequestDetails details);

public abstract void recreateHttpBackend();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request.Builder;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
Expand Down Expand Up @@ -173,10 +174,29 @@ public synchronized void recreateHttpBackend() {
httpBackend = new OKHTTPBackend();
}

@Override
public String resolveRedirectUri(final String url) {
try {
final Builder builder = new Builder();
final okhttp3.Request headRequest = builder.url(url).head().build();
final OkHttpClient noRedirectsClient =
mClient.newBuilder().followRedirects(false).build();
try (Response response = noRedirectsClient.newCall(headRequest).execute()) {
if (response.isRedirect()) {
return response.header("Location");
}
}
} catch (final IOException e) {
Log.e(TAG, "Failed to resolve redirect URL", e);
return null;
}
return null;
}

@Override
public Request prepareRequest(final Context context, final RequestDetails details) {

final okhttp3.Request.Builder builder = new okhttp3.Request.Builder();
final Builder builder = new Builder();

builder.header("User-Agent", Constants.ua(context));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*******************************************************************************
* This file is part of RedReader.
*
* RedReader is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RedReader is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RedReader. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

package org.quantumbadger.redreader.reddit.url;

import android.net.Uri;

import androidx.annotation.Nullable;

import java.util.List;

public class OpaqueSharedURL extends RedditURLParser.RedditURL {

@Nullable
public final String subreddit;
@Nullable public final String shareKey;

public OpaqueSharedURL(@Nullable final String subreddit, @Nullable final String shareKey) {
this.subreddit = subreddit;
this.shareKey = shareKey;
}

@Override
public Uri generateJsonUri() {
return null;
}

@Override
public int pathType() {
return RedditURLParser.OPAQUE_SHARED_URL;
}

public static OpaqueSharedURL parse(final Uri uri) {
// URLs look like https://reddit.com/r/RedReader/s/<alphanumeric>
// first pull out the path segments and ensure they match the example (should be 4)
final List<String> pathSegments = uri.getPathSegments();
if (pathSegments.size() != 4) {
return null;
}

// ensure the first segment is "r" and the third is "s"
if (!pathSegments.get(0).equals("r") || !pathSegments.get(2).equals("s")) {
return null;
}

return new OpaqueSharedURL(pathSegments.get(1), pathSegments.get(3));
}

public static Uri getUrlToFetch(final OpaqueSharedURL url) {
return Uri.parse(String.format("https://www.reddit.com/r/%s/s/%s", url.subreddit, url.shareKey));
}

@Nullable
public String getSubreddit() {
return subreddit;
}

@Nullable
public String getShareKey() {
return shareKey;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class RedditURLParser {
public static final int POST_COMMENT_LISTING_URL = 7;
public static final int MULTIREDDIT_POST_LISTING_URL = 8;
public static final int COMPOSE_MESSAGE_URL = 9;
public static final int OPAQUE_SHARED_URL = 10;

@IntDef({
SUBREDDIT_POST_LISTING_URL,
Expand All @@ -52,7 +53,9 @@ public class RedditURLParser {
UNKNOWN_COMMENT_LISTING_URL,
POST_COMMENT_LISTING_URL,
MULTIREDDIT_POST_LISTING_URL,
COMPOSE_MESSAGE_URL})
COMPOSE_MESSAGE_URL,
OPAQUE_SHARED_URL
})
@Retention(RetentionPolicy.SOURCE)
public @interface PathType {
}
Expand Down Expand Up @@ -122,6 +125,13 @@ public static RedditURL parse(final Uri rawUri) {

final Uri uri = optionalUri.get();

{
final OpaqueSharedURL opaqueSharedURL = OpaqueSharedURL.parse(uri);
if(opaqueSharedURL != null) {
return opaqueSharedURL;
}
}

{
final SubredditPostListURL subredditPostListURL = SubredditPostListURL.parse(uri);
if(subredditPostListURL != null) {
Expand Down

0 comments on commit 614e50a

Please sign in to comment.