diff options
author | David Luhmer <david-dev@live.de> | 2021-12-14 22:23:45 +0300 |
---|---|---|
committer | David Luhmer <david-dev@live.de> | 2021-12-14 22:23:45 +0300 |
commit | c8de06979599bf64a100e01997c33d9ea75fe1bc (patch) | |
tree | fbd15fd754cf68af670fb56a0335f0fbb811e291 /News-Android-App/src/main/java | |
parent | dfe0bfc9e26c098ec9c72cb8c088033a3c5b3276 (diff) |
add support for relative and absolute image path / update app version
Diffstat (limited to 'News-Android-App/src/main/java')
5 files changed, 112 insertions, 9 deletions
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogActivity.java index c75eab8e..0c912959 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogActivity.java @@ -54,6 +54,7 @@ import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledExcepti import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; import com.nextcloud.android.sso.helper.SingleAccountHelper; import com.nextcloud.android.sso.helper.VersionCheckHelper; +import com.nextcloud.android.sso.model.FilesAppType; import com.nextcloud.android.sso.model.SingleSignOnAccount; import com.nextcloud.android.sso.ui.UiExceptionManager; @@ -164,7 +165,7 @@ public class LoginDialogActivity extends AppCompatActivity { } public void startSingleSignOn() { - if (!VersionCheckHelper.verifyMinVersion(LoginDialogActivity.this, MIN_NEXTCLOUD_FILES_APP_VERSION_CODE)) { + if (!VersionCheckHelper.verifyMinVersion(LoginDialogActivity.this, MIN_NEXTCLOUD_FILES_APP_VERSION_CODE, FilesAppType.PROD)) { // Dialog will be shown automatically return; } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/RssItemToHtmlTask.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/RssItemToHtmlTask.java index 6bb0b970..0bd768db 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/RssItemToHtmlTask.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/async_tasks/RssItemToHtmlTask.java @@ -133,7 +133,7 @@ public class RssItemToHtmlTask extends AsyncTask<Void, Void, String> { if(!incognitoMode) { // If incognito mode is disabled, try getting images from cache - description = getDescriptionWithCachedImages(description).trim(); + description = getDescriptionWithCachedImages(rssItem.getLink(), description).trim(); } else { // When incognito is on, we need to provide some error handling //description = description.replaceAll("<img", "<img onerror=\"this.style='width: 40px !important; height: 40px !important'\" "); @@ -234,16 +234,17 @@ public class RssItemToHtmlTask extends AsyncTask<Void, Void, String> { ); } - private static String getDescriptionWithCachedImages(String text) { - List<String> links = ImageHandler.getImageLinksFromText(text); + private static String getDescriptionWithCachedImages(String articleUrl, String text) { + List<String> links = ImageHandler.getImageLinksFromText(articleUrl, text); DiskCache diskCache = ImageLoader.getInstance().getDiskCache(); for(String link : links) { link = link.trim(); try { File file = diskCache.get(link); - if(file != null) + if(file != null) { text = text.replace(link, "file://" + file.getAbsolutePath()); + } } catch(Exception ex) { ex.printStackTrace(); } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ImageHandler.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ImageHandler.java index 1b838342..bdb0bb33 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ImageHandler.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/helper/ImageHandler.java @@ -21,18 +21,23 @@ package de.luhmer.owncloudnewsreader.helper; +import android.util.Log; + import com.nostra13.universalimageloader.core.ImageLoader; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ImageHandler { + private static final String TAG = "[ImageHandler]"; private static final Pattern patternImg = Pattern.compile("<img[^>]*>"); private static final Pattern patternImgSrcLink = Pattern.compile("src=\"(.*?)\""); - public static List<String> getImageLinksFromText(String text) + public static List<String> getImageLinksFromText(String articleUrl, String text) { List<String> links = new ArrayList<>(); @@ -45,12 +50,100 @@ public class ImageHandler { if(link != null && link.startsWith("//")) { //Maybe the text contains image urls without http or https prefix. link = "https:" + link; } - links.add(link); + + // the android universal image loader doesn't support svg images. Therefore we don't want to load them through UIL + if(link.endsWith(".svg")) { + Log.d(TAG, "detected unsupported svg image in article: " + articleUrl + " -> " + link); + } else { + links.add(link); + } } } return links; } + public static String fixBrokenImageLinksInArticle(String articleUrl, String text) + { + Matcher matcher = patternImg.matcher(text); + // Check all occurrences + while (matcher.find()) { + Matcher matcherSrcLink = patternImgSrcLink.matcher(matcher.group()); + if(matcherSrcLink.find()) { + String link = matcherSrcLink.group(1); + String originalLink = link; + String originalArticleUrl = articleUrl; + if(link != null) { + if(link.startsWith("//")) { //Maybe the text contains image urls without http or https prefix. + link = "https:" + link; + } else if (link.startsWith("/")) { // detected absolute url + try { + URI uri = new URI(articleUrl); + String domain = uri.getHost(); + link = uri.getScheme() + "://" + domain + link; + } catch (URISyntaxException e) { + e.printStackTrace(); + Log.e(TAG, e.toString()); + } + } else { + // check if we have relative urls such as + // ./abc.jpeg or ./../abc.jpeg, ../abc.jpeg or ../../abc.jpeg + boolean linkNeedsHost = false; + if(link.startsWith("./")) { + link = link.substring(2); // remove ./ from link + linkNeedsHost = true; + } + + // if link is relative without anything else in front (e.g. pix/wow.svg) + if(!link.startsWith("http") && !link.startsWith(".")) { + linkNeedsHost = true; + if(!articleUrl.endsWith("/")) { + // remove last part of article url to get a relative url + articleUrl = sliceLastPathOfUrl(articleUrl); + } + } + + // in case the article url is of type articles/matrix-vs-xmpp.html we need to remove the file plus the first part of the url + if(link.startsWith("../") && !articleUrl.endsWith("/")) { + linkNeedsHost = true; + articleUrl = sliceLastPathOfUrl(articleUrl); + articleUrl = sliceLastPathOfUrl(articleUrl); + link = link.substring(3); // remove ../ from link + } + + // if the article urls ends with an / we can just remove it piece by piece + while(link.startsWith("../")) { + linkNeedsHost = true; + articleUrl = sliceLastPathOfUrl(articleUrl); + link = link.substring(3); // remove ../ from link + } + + if(linkNeedsHost) { + link = articleUrl + "/" + link; + } + } + } + + if(!originalLink.equals(link)) { + Log.d(TAG, "Fixed link from: " + originalArticleUrl + " and " + originalLink + " -> " + link); + text = text.replaceAll(originalLink, link); + } + } + } + return text; + } + + private static String sliceLastPathOfUrl(String url) { + int idx = url.lastIndexOf("/"); + int countOfSlashes = url.split("/").length - 1; + // Log.d(TAG, url + " " + countOfSlashes); + // make sure we don't count into the domain name (at least two slashes for ://) + if(idx > 0 && countOfSlashes > 2) { + return url.substring(0, idx); + } else { + return url; + } + } + public static void clearCache() { if(ImageLoader.getInstance().isInited()) { diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/nextcloud/InsertRssItemIntoDatabase.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/nextcloud/InsertRssItemIntoDatabase.java index 1088e120..4e0b3c57 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/nextcloud/InsertRssItemIntoDatabase.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/nextcloud/InsertRssItemIntoDatabase.java @@ -109,11 +109,19 @@ class InsertRssItemIntoDatabase { Log.w("InsertRssItem", "Large rss item detected - " + content.length() + " chars / " + content.length()/1024d/1024d + "mb - url:" + rssItem.getLink()); } + try { + // try fixing relative image links + content = ImageHandler.fixBrokenImageLinksInArticle(url, content); + } catch(Exception ex) { + ex.printStackTrace(); + Log.e(TAG, ex.toString()); + } + rssItem.setBody(content); String mediaThumbnail = getStringOrEmpty("mediaThumbnail", e); // Possible XSS Fields if(mediaThumbnail.isEmpty()) { - List<String> images = ImageHandler.getImageLinksFromText(content); + List<String> images = ImageHandler.getImageLinksFromText(url, content); if(images.size() > 0) { Log.d(TAG, "extracted mediaThumbnail from body"); mediaThumbnail = images.get(0); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java index ea80835a..7542fc46 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java @@ -129,7 +129,7 @@ public class DownloadImagesService extends JobIntentService { List<String> links = new ArrayList<>(); for(RssItem rssItem : rssItemList) { String body = rssItem.getBody(); - links.addAll(ImageHandler.getImageLinksFromText(body)); + links.addAll(ImageHandler.getImageLinksFromText(rssItem.getLink(), body)); if(links.size() > 10000) { NextcloudNotificationManager.showNotificationImageDownloadLimitReached(this, CHANNEL_ID, 10000); |