From 52e4a2a0b72d697d97bde94361fb35360d37b91e Mon Sep 17 00:00:00 2001 From: Athou Date: Sat, 22 Jun 2013 21:36:55 +0200 Subject: [PATCH] proxy images through commafeed (#231) --- .../commafeed/backend/feeds/FeedUtils.java | 56 +++++++++++++++++++ .../backend/model/ApplicationSettings.java | 9 +++ .../com/commafeed/frontend/model/Entry.java | 6 +- .../frontend/rest/resources/AbstractREST.java | 4 ++ .../frontend/rest/resources/CategoryREST.java | 10 +++- .../frontend/rest/resources/EntryREST.java | 3 +- .../frontend/rest/resources/FeedREST.java | 3 +- .../frontend/rest/resources/ServerREST.java | 20 +++++++ .../resources/changelogs/db.changelog-1.1.xml | 9 ++- src/main/webapp/templates/admin.settings.html | 6 ++ 10 files changed, 118 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/commafeed/backend/feeds/FeedUtils.java b/src/main/java/com/commafeed/backend/feeds/FeedUtils.java index a887c176..61d951bd 100644 --- a/src/main/java/com/commafeed/backend/feeds/FeedUtils.java +++ b/src/main/java/com/commafeed/backend/feeds/FeedUtils.java @@ -21,6 +21,7 @@ import org.jsoup.nodes.Element; import org.jsoup.nodes.Entities.EscapeMode; import org.jsoup.safety.Cleaner; import org.jsoup.safety.Whitelist; +import org.jsoup.select.Elements; import org.mozilla.universalchardet.UniversalDetector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,6 +31,7 @@ import org.w3c.dom.css.CSSStyleDeclaration; import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.FeedEntry; import com.commafeed.backend.model.FeedSubscription; +import com.google.api.client.util.Base64; import com.google.api.client.util.Lists; import com.google.gwt.i18n.client.HasDirection.Direction; import com.google.gwt.i18n.shared.BidiUtils; @@ -38,6 +40,7 @@ import com.steadystate.css.parser.CSSOMParser; public class FeedUtils { protected static Logger log = LoggerFactory.getLogger(FeedUtils.class); + private static final List ALLOWED_IFRAME_CSS_RULES = Arrays.asList( "height", "width", "border"); private static final char[] DISALLOWED_IFRAME_CSS_RULE_CHARACTERS = new char[] { @@ -358,4 +361,57 @@ public class FeedUtils { + subscription.getId(); } + public static String proxyImages(String content, String publicUrl, + boolean proxyImages) { + if (!proxyImages) { + return content; + } + if (StringUtils.isBlank(content)) { + return content; + } + + log.info("cc"); + Document doc = Jsoup.parse(content); + Elements elements = doc.select("img"); + log.info("{}", elements.size()); + for (Element element : elements) { + String href = element.attr("src"); + log.info(href); + if (href != null) { + String proxy = removeTrailingSlash(publicUrl) + "/rest/server/proxy?u=" + + imageProxyEncoder(href); + log.info(proxy); + element.attr("src", proxy); + } + } + + return doc.body().html(); + } + + public static String rot13(String msg) { + StringBuilder message = new StringBuilder(); + + for (char c : msg.toCharArray()) { + if (c >= 'a' && c <= 'm') + c += 13; + else if (c >= 'n' && c <= 'z') + c -= 13; + else if (c >= 'A' && c <= 'M') + c += 13; + else if (c >= 'N' && c <= 'Z') + c -= 13; + message.append(c); + } + + return message.toString(); + } + + public static String imageProxyEncoder(String url) { + return Base64.encodeBase64String(rot13(url).getBytes()); + } + + public static String imageProxyDecoder(String code) { + return rot13(new String(Base64.decodeBase64(code))); + } + } diff --git a/src/main/java/com/commafeed/backend/model/ApplicationSettings.java b/src/main/java/com/commafeed/backend/model/ApplicationSettings.java index 0989e22c..4e83086d 100644 --- a/src/main/java/com/commafeed/backend/model/ApplicationSettings.java +++ b/src/main/java/com/commafeed/backend/model/ApplicationSettings.java @@ -32,6 +32,7 @@ public class ApplicationSettings extends AbstractModel { private boolean pubsubhubbub; private boolean feedbackButton = true; private String logLevel = Level.INFO.toString(); + private boolean imageProxyEnabled; @Column(length = 255) private String announcement; @@ -173,4 +174,12 @@ public class ApplicationSettings extends AbstractModel { this.logLevel = logLevel; } + public boolean isImageProxyEnabled() { + return imageProxyEnabled; + } + + public void setImageProxyEnabled(boolean imageProxyEnabled) { + this.imageProxyEnabled = imageProxyEnabled; + } + } diff --git a/src/main/java/com/commafeed/frontend/model/Entry.java b/src/main/java/com/commafeed/frontend/model/Entry.java index dbb4264d..41ae271e 100644 --- a/src/main/java/com/commafeed/frontend/model/Entry.java +++ b/src/main/java/com/commafeed/frontend/model/Entry.java @@ -24,7 +24,8 @@ import com.wordnik.swagger.annotations.ApiProperty; @ApiClass("Entry details") public class Entry implements Serializable { - public static Entry build(FeedEntryStatus status, String publicUrl) { + public static Entry build(FeedEntryStatus status, String publicUrl, + boolean proxyImages) { Entry entry = new Entry(); FeedEntry feedEntry = status.getEntry(); @@ -36,7 +37,8 @@ public class Entry implements Serializable { entry.setId(String.valueOf(feedEntry.getId())); entry.setGuid(feedEntry.getGuid()); entry.setTitle(feedEntry.getContent().getTitle()); - entry.setContent(feedEntry.getContent().getContent()); + entry.setContent(FeedUtils.proxyImages(feedEntry.getContent() + .getContent(), publicUrl, proxyImages)); entry.setRtl(FeedUtils.isRTL(feedEntry)); entry.setAuthor(feedEntry.getAuthor()); entry.setEnclosureUrl(feedEntry.getContent().getEnclosureUrl()); diff --git a/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java b/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java index b50fd4e0..42ad3972 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java @@ -25,6 +25,7 @@ import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.util.crypt.Base64; import com.commafeed.backend.DatabaseCleaner; +import com.commafeed.backend.HttpGetter; import com.commafeed.backend.MetricsBean; import com.commafeed.backend.StartupBean; import com.commafeed.backend.dao.FeedCategoryDAO; @@ -128,6 +129,9 @@ public abstract class AbstractREST { @Inject DatabaseCleaner cleaner; + @Inject + HttpGetter httpGetter; + @PostConstruct public void init() { CommaFeedApplication app = CommaFeedApplication.get(); diff --git a/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java b/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java index 9a874e97..61af8bd4 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java @@ -96,7 +96,8 @@ public class CategoryREST extends AbstractResourceREST { for (FeedEntryStatus status : list) { entries.getEntries().add( Entry.build(status, applicationSettingsService.get() - .getPublicUrl())); + .getPublicUrl(), applicationSettingsService + .get().isImageProxyEnabled())); } } else if (STARRED.equals(id)) { @@ -106,7 +107,8 @@ public class CategoryREST extends AbstractResourceREST { for (FeedEntryStatus status : starred) { entries.getEntries().add( Entry.build(status, applicationSettingsService.get() - .getPublicUrl())); + .getPublicUrl(), applicationSettingsService + .get().isImageProxyEnabled())); } } else { FeedCategory feedCategory = feedCategoryDAO.findById(getUser(), @@ -127,7 +129,9 @@ public class CategoryREST extends AbstractResourceREST { for (FeedEntryStatus status : list) { entries.getEntries().add( Entry.build(status, applicationSettingsService - .get().getPublicUrl())); + .get().getPublicUrl(), + applicationSettingsService.get() + .isImageProxyEnabled())); } entries.setName(feedCategory.getName()); } diff --git a/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java b/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java index dd42a988..92f7c856 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java @@ -75,7 +75,8 @@ public class EntryREST extends AbstractResourceREST { .findByKeywords(getUser(), keywords, offset, limit); for (FeedEntryStatus status : entriesStatus) { list.add(Entry.build(status, applicationSettingsService.get() - .getPublicUrl())); + .getPublicUrl(), applicationSettingsService.get() + .isImageProxyEnabled())); } entries.setName("Search for : " + keywords); diff --git a/src/main/java/com/commafeed/frontend/rest/resources/FeedREST.java b/src/main/java/com/commafeed/frontend/rest/resources/FeedREST.java index f1957e9b..9ac42783 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/FeedREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/FeedREST.java @@ -113,7 +113,8 @@ public class FeedREST extends AbstractResourceREST { for (FeedEntryStatus status : list) { entries.getEntries().add( Entry.build(status, applicationSettingsService.get() - .getPublicUrl())); + .getPublicUrl(), applicationSettingsService + .get().isImageProxyEnabled())); } boolean hasMore = entries.getEntries().size() > limit; diff --git a/src/main/java/com/commafeed/frontend/rest/resources/ServerREST.java b/src/main/java/com/commafeed/frontend/rest/resources/ServerREST.java index b5e57061..b95cc15f 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/ServerREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/ServerREST.java @@ -2,8 +2,13 @@ package com.commafeed.frontend.rest.resources; import javax.ws.rs.GET; import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import com.commafeed.backend.HttpGetter.HttpResult; +import com.commafeed.backend.feeds.FeedUtils; import com.commafeed.frontend.model.ServerInfo; import com.wordnik.swagger.annotations.Api; import com.wordnik.swagger.annotations.ApiOperation; @@ -23,4 +28,19 @@ public class ServerREST extends AbstractResourceREST { startupBean.getSupportedLanguages()); return Response.ok(infos).build(); } + + @Path("/proxy") + @GET + @ApiOperation(value = "proxy image") + @Produces("image/png") + public Response get(@QueryParam("u") String url) { + url = FeedUtils.imageProxyDecoder(url); + try { + HttpResult result = httpGetter.getBinary(url); + return Response.ok(result.getContent()).build(); + } catch (Exception e) { + return Response.status(Status.SERVICE_UNAVAILABLE) + .entity(e.getMessage()).build(); + } + } } diff --git a/src/main/resources/changelogs/db.changelog-1.1.xml b/src/main/resources/changelogs/db.changelog-1.1.xml index 07b5e7d4..f66b6b7f 100644 --- a/src/main/resources/changelogs/db.changelog-1.1.xml +++ b/src/main/resources/changelogs/db.changelog-1.1.xml @@ -222,6 +222,13 @@ update USERS set created = lastLogin - + + + + + + + update APPLICATIONSETTINGS set imageProxyEnabled=false + diff --git a/src/main/webapp/templates/admin.settings.html b/src/main/webapp/templates/admin.settings.html index 1693eda2..a19e9841 100644 --- a/src/main/webapp/templates/admin.settings.html +++ b/src/main/webapp/templates/admin.settings.html @@ -137,6 +137,12 @@ +
+ +
+ +
+