From e4daf856661958be1f88f0d3861823df91c78b1e Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Fri, 24 Jul 2015 10:39:21 +0200 Subject: [PATCH] Use unique IDs for images --- .../sone/core/ConfigurationSoneParser.java | 2 +- .../java/net/pterodactylus/sone/core/Core.java | 2 +- .../java/net/pterodactylus/sone/data/Image.java | 1 + .../java/net/pterodactylus/sone/data/Profile.java | 2 +- .../java/net/pterodactylus/sone/data/Sone.java | 2 + .../pterodactylus/sone/data/impl/IdOnlySone.java | 7 +++ .../pterodactylus/sone/data/impl/ImageImpl.java | 8 +++ .../net/pterodactylus/sone/data/impl/SoneImpl.java | 15 ++++++ .../pterodactylus/sone/template/BuildIdFilter.java | 57 ++++++++++++++++++++++ .../sone/template/ProfileAccessor.java | 2 +- .../pterodactylus/sone/web/DeleteImagePage.java | 4 +- .../net/pterodactylus/sone/web/EditAlbumPage.java | 2 +- .../net/pterodactylus/sone/web/EditImagePage.java | 3 +- .../pterodactylus/sone/web/EditProfilePage.java | 5 +- .../net/pterodactylus/sone/web/WebInterface.java | 2 + src/main/resources/templates/editProfile.html | 2 +- src/main/resources/templates/include/head.html | 2 +- src/main/resources/templates/include/soneMenu.html | 2 +- src/main/resources/templates/include/viewPost.html | 2 +- .../resources/templates/include/viewReply.html | 2 +- src/main/resources/templates/insert/sone.xml | 4 +- .../sone/core/FreenetInterfaceTest.java | 2 + .../pterodactylus/sone/core/SoneParserTest.java | 8 +-- .../sone/template/BuildIdFilterTest.java | 51 +++++++++++++++++++ 24 files changed, 170 insertions(+), 19 deletions(-) create mode 100644 src/main/java/net/pterodactylus/sone/template/BuildIdFilter.java create mode 100644 src/test/java/net/pterodactylus/sone/template/BuildIdFilterTest.java diff --git a/src/main/java/net/pterodactylus/sone/core/ConfigurationSoneParser.java b/src/main/java/net/pterodactylus/sone/core/ConfigurationSoneParser.java index a29856b..02c10db 100644 --- a/src/main/java/net/pterodactylus/sone/core/ConfigurationSoneParser.java +++ b/src/main/java/net/pterodactylus/sone/core/ConfigurationSoneParser.java @@ -271,7 +271,7 @@ public class ConfigurationSoneParser { .setHeight(height) .update(); album.addImage(image); - images.put(image.getId(), image); + images.put(imageId, image); } } diff --git a/src/main/java/net/pterodactylus/sone/core/Core.java b/src/main/java/net/pterodactylus/sone/core/Core.java index 8e00e23..d0b31d0 100644 --- a/src/main/java/net/pterodactylus/sone/core/Core.java +++ b/src/main/java/net/pterodactylus/sone/core/Core.java @@ -1530,7 +1530,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, continue; } String imagePrefix = sonePrefix + "/Images/" + imageCounter++; - configuration.getStringValue(imagePrefix + "/ID").setValue(image.getId()); + configuration.getStringValue(imagePrefix + "/ID").setValue(image.getInternalId()); configuration.getStringValue(imagePrefix + "/Album").setValue(album.getInternalId()); configuration.getStringValue(imagePrefix + "/Key").setValue(image.getKey()); configuration.getStringValue(imagePrefix + "/Title").setValue(image.getTitle()); diff --git a/src/main/java/net/pterodactylus/sone/data/Image.java b/src/main/java/net/pterodactylus/sone/data/Image.java index 22ddc29..f2ef88d 100644 --- a/src/main/java/net/pterodactylus/sone/data/Image.java +++ b/src/main/java/net/pterodactylus/sone/data/Image.java @@ -30,6 +30,7 @@ public interface Image extends Identified, Fingerprintable { * @return The ID of this image */ String getId(); + String getInternalId(); /** * Returns the Sone this image belongs to. diff --git a/src/main/java/net/pterodactylus/sone/data/Profile.java b/src/main/java/net/pterodactylus/sone/data/Profile.java index 4970cf9..679196b 100644 --- a/src/main/java/net/pterodactylus/sone/data/Profile.java +++ b/src/main/java/net/pterodactylus/sone/data/Profile.java @@ -243,7 +243,7 @@ public class Profile implements Fingerprintable { return this; } checkArgument(avatar.getSone().equals(sone), "avatar must belong to Sone"); - this.avatar = avatar.getId(); + this.avatar = avatar.getInternalId(); return this; } diff --git a/src/main/java/net/pterodactylus/sone/data/Sone.java b/src/main/java/net/pterodactylus/sone/data/Sone.java index e64a388..4d0905f 100644 --- a/src/main/java/net/pterodactylus/sone/data/Sone.java +++ b/src/main/java/net/pterodactylus/sone/data/Sone.java @@ -35,6 +35,7 @@ import net.pterodactylus.sone.freenet.wot.Identity; import net.pterodactylus.sone.freenet.wot.OwnIdentity; import net.pterodactylus.sone.template.SoneAccessor; +import com.google.common.base.Optional; import freenet.keys.FreenetURI; import com.google.common.base.Function; @@ -502,6 +503,7 @@ public interface Sone extends Identified, Fingerprintable, Comparable { * @return The root album of this Sone */ Album getRootAlbum(); + Optional getImageByInternalId(final String internalId); /** * Returns Sone-specific options. diff --git a/src/main/java/net/pterodactylus/sone/data/impl/IdOnlySone.java b/src/main/java/net/pterodactylus/sone/data/impl/IdOnlySone.java index e9a0c57..85402ce 100644 --- a/src/main/java/net/pterodactylus/sone/data/impl/IdOnlySone.java +++ b/src/main/java/net/pterodactylus/sone/data/impl/IdOnlySone.java @@ -9,6 +9,7 @@ import java.util.Set; import net.pterodactylus.sone.data.Album; import net.pterodactylus.sone.data.Client; +import net.pterodactylus.sone.data.Image; import net.pterodactylus.sone.data.Post; import net.pterodactylus.sone.data.PostReply; import net.pterodactylus.sone.data.Profile; @@ -16,6 +17,7 @@ import net.pterodactylus.sone.data.Sone; import net.pterodactylus.sone.data.SoneOptions; import net.pterodactylus.sone.freenet.wot.Identity; +import com.google.common.base.Optional; import freenet.keys.FreenetURI; import com.google.common.base.Objects; @@ -219,6 +221,11 @@ public class IdOnlySone implements Sone { } @Override + public Optional getImageByInternalId(String internalId) { + return Optional.absent(); + } + + @Override public SoneOptions getOptions() { return null; } diff --git a/src/main/java/net/pterodactylus/sone/data/impl/ImageImpl.java b/src/main/java/net/pterodactylus/sone/data/impl/ImageImpl.java index 2df98b1..b385cfd 100644 --- a/src/main/java/net/pterodactylus/sone/data/impl/ImageImpl.java +++ b/src/main/java/net/pterodactylus/sone/data/impl/ImageImpl.java @@ -25,6 +25,7 @@ import static com.google.common.base.Preconditions.checkState; import java.util.UUID; import net.pterodactylus.sone.data.Album; +import net.pterodactylus.sone.data.IdBuilder; import net.pterodactylus.sone.data.Image; import net.pterodactylus.sone.data.Sone; @@ -39,6 +40,8 @@ import com.google.common.hash.Hashing; */ public class ImageImpl implements Image { + private final IdBuilder idBuilder = new IdBuilder(); + /** The ID of the image. */ private final String id; @@ -88,6 +91,11 @@ public class ImageImpl implements Image { @Override public String getId() { + return idBuilder.buildId(sone.getId(), id); + } + + @Override + public String getInternalId() { return id; } diff --git a/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java b/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java index f7ebfb1..97fe8eb 100644 --- a/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java +++ b/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java @@ -30,9 +30,11 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nullable; import net.pterodactylus.sone.data.Album; import net.pterodactylus.sone.data.Client; +import net.pterodactylus.sone.data.Image; import net.pterodactylus.sone.data.Post; import net.pterodactylus.sone.data.PostReply; import net.pterodactylus.sone.data.Profile; @@ -44,6 +46,9 @@ import net.pterodactylus.sone.database.Database; import net.pterodactylus.sone.freenet.wot.Identity; import net.pterodactylus.sone.freenet.wot.OwnIdentity; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; import freenet.keys.FreenetURI; import com.google.common.hash.Hasher; @@ -584,6 +589,16 @@ public class SoneImpl implements Sone { return rootAlbum; } + @Override + public Optional getImageByInternalId(final String internalId) { + return FluentIterable.from(toAllImages.apply(this)).filter(new Predicate() { + @Override + public boolean apply(@Nullable Image input) { + return (input != null) && input.getInternalId().equals(internalId); + } + }).first(); + } + /** * Returns Sone-specific options. * diff --git a/src/main/java/net/pterodactylus/sone/template/BuildIdFilter.java b/src/main/java/net/pterodactylus/sone/template/BuildIdFilter.java new file mode 100644 index 0000000..321743a --- /dev/null +++ b/src/main/java/net/pterodactylus/sone/template/BuildIdFilter.java @@ -0,0 +1,57 @@ +package net.pterodactylus.sone.template; + +import java.util.Map; + +import javax.annotation.Nullable; + +import net.pterodactylus.sone.data.IdBuilder; +import net.pterodactylus.sone.data.Sone; +import net.pterodactylus.util.template.Filter; +import net.pterodactylus.util.template.TemplateContext; + +import com.google.common.base.Function; +import com.google.common.base.Optional; + +/** + * Filter that {@link IdBuilder builds IDs} from a piped-in element ID and a Sone or Sone ID given as parameter “sone.” + * + * @author David ‘Bombe’ Roden + */ +public class BuildIdFilter implements Filter { + + private final IdBuilder idBuilder = new IdBuilder(); + + @Override + public Object format(TemplateContext templateContext, Object data, Map parameters) { + Optional soneId = getSoneId(parameters); + if (!soneId.isPresent()) { + return null; + } + Optional elementId = Optional.fromNullable(data).transform(getStringValue()); + if (!elementId.isPresent()) { + return null; + } + return idBuilder.buildId(soneId.get(), elementId.get()); + } + + private Optional getSoneId(Map parameters) { + Object soneObject = parameters.get("sone"); + if (soneObject instanceof String) { + return Optional.of((String) soneObject); + } else if (soneObject instanceof Sone) { + return Optional.of(((Sone) soneObject).getId()); + } + return Optional.absent(); + } + + private Function getStringValue() { + return new Function() { + @Nullable + @Override + public String apply(Object input) { + return (input != null) ? input.toString() : null; + } + }; + } + +} diff --git a/src/main/java/net/pterodactylus/sone/template/ProfileAccessor.java b/src/main/java/net/pterodactylus/sone/template/ProfileAccessor.java index 762bc14..ce29caa 100644 --- a/src/main/java/net/pterodactylus/sone/template/ProfileAccessor.java +++ b/src/main/java/net/pterodactylus/sone/template/ProfileAccessor.java @@ -65,7 +65,7 @@ public class ProfileAccessor extends ReflectionAccessor { if (avatarId == null) { return null; } - if (core.getImage(avatarId, false) == null) { + if (!currentSone.getImageByInternalId(avatarId).isPresent()) { /* avatar ID but no matching image? show nothing. */ return null; } diff --git a/src/main/java/net/pterodactylus/sone/web/DeleteImagePage.java b/src/main/java/net/pterodactylus/sone/web/DeleteImagePage.java index 77f3ab8..9d50bfb 100644 --- a/src/main/java/net/pterodactylus/sone/web/DeleteImagePage.java +++ b/src/main/java/net/pterodactylus/sone/web/DeleteImagePage.java @@ -17,6 +17,7 @@ package net.pterodactylus.sone.web; +import net.pterodactylus.sone.data.IdBuilder; import net.pterodactylus.sone.data.Image; import net.pterodactylus.sone.web.page.FreenetRequest; import net.pterodactylus.util.template.Template; @@ -52,7 +53,8 @@ public class DeleteImagePage extends SoneTemplatePage { @Override protected void processTemplate(FreenetRequest request, TemplateContext templateContext) throws RedirectException { super.processTemplate(request, templateContext); - String imageId = (request.getMethod() == Method.POST) ? request.getHttpRequest().getPartAsStringFailsafe("image", 36) : request.getHttpRequest().getParam("image"); + String imageId = (request.getMethod() == Method.POST) ? request.getHttpRequest().getPartAsStringFailsafe("image", IdBuilder.ID_STRING_LENGTH) + : request.getHttpRequest().getParam("image"); Image image = webInterface.getCore().getImage(imageId, false); if (image == null) { throw new RedirectException("invalid.html"); diff --git a/src/main/java/net/pterodactylus/sone/web/EditAlbumPage.java b/src/main/java/net/pterodactylus/sone/web/EditAlbumPage.java index eca15de..aab4614 100644 --- a/src/main/java/net/pterodactylus/sone/web/EditAlbumPage.java +++ b/src/main/java/net/pterodactylus/sone/web/EditAlbumPage.java @@ -69,7 +69,7 @@ public class EditAlbumPage extends SoneTemplatePage { webInterface.getCore().touchConfiguration(); throw new RedirectException("imageBrowser.html?album=" + album.getParent().getId()); } - String albumImageId = request.getHttpRequest().getPartAsStringFailsafe("album-image", 36); + String albumImageId = request.getHttpRequest().getPartAsStringFailsafe("album-image", IdBuilder.ID_STRING_LENGTH); if (webInterface.getCore().getImage(albumImageId, false) == null) { albumImageId = null; } diff --git a/src/main/java/net/pterodactylus/sone/web/EditImagePage.java b/src/main/java/net/pterodactylus/sone/web/EditImagePage.java index 178add1..304b19c 100644 --- a/src/main/java/net/pterodactylus/sone/web/EditImagePage.java +++ b/src/main/java/net/pterodactylus/sone/web/EditImagePage.java @@ -17,6 +17,7 @@ package net.pterodactylus.sone.web; +import net.pterodactylus.sone.data.IdBuilder; import net.pterodactylus.sone.data.Image; import net.pterodactylus.sone.text.TextFilter; import net.pterodactylus.sone.web.page.FreenetRequest; @@ -54,7 +55,7 @@ public class EditImagePage extends SoneTemplatePage { protected void processTemplate(FreenetRequest request, TemplateContext templateContext) throws RedirectException { super.processTemplate(request, templateContext); if (request.getMethod() == Method.POST) { - String imageId = request.getHttpRequest().getPartAsStringFailsafe("image", 36); + String imageId = request.getHttpRequest().getPartAsStringFailsafe("image", IdBuilder.ID_STRING_LENGTH); String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 256); Image image = webInterface.getCore().getImage(imageId, false); if (image == null) { diff --git a/src/main/java/net/pterodactylus/sone/web/EditProfilePage.java b/src/main/java/net/pterodactylus/sone/web/EditProfilePage.java index 162d637..47fd8c3 100644 --- a/src/main/java/net/pterodactylus/sone/web/EditProfilePage.java +++ b/src/main/java/net/pterodactylus/sone/web/EditProfilePage.java @@ -22,6 +22,7 @@ import static net.pterodactylus.sone.utils.NumberParsers.parseInt; import java.util.List; +import net.pterodactylus.sone.data.IdBuilder; import net.pterodactylus.sone.data.Profile; import net.pterodactylus.sone.data.Profile.DuplicateField; import net.pterodactylus.sone.data.Profile.Field; @@ -80,12 +81,12 @@ public class EditProfilePage extends SoneTemplatePage { birthDay = parseInt(request.getHttpRequest().getPartAsStringFailsafe("birth-day", 256).trim(), null); birthMonth = parseInt(request.getHttpRequest().getPartAsStringFailsafe("birth-month", 256).trim(), null); birthYear = parseInt(request.getHttpRequest().getPartAsStringFailsafe("birth-year", 256).trim(), null); - avatarId = request.getHttpRequest().getPartAsStringFailsafe("avatarId", 36); + avatarId = request.getHttpRequest().getPartAsStringFailsafe("avatarId", IdBuilder.ID_STRING_LENGTH); profile.setFirstName(firstName.length() > 0 ? firstName : null); profile.setMiddleName(middleName.length() > 0 ? middleName : null); profile.setLastName(lastName.length() > 0 ? lastName : null); profile.setBirthDay(birthDay).setBirthMonth(birthMonth).setBirthYear(birthYear); - profile.setAvatar(webInterface.getCore().getImage(avatarId, false)); + profile.setAvatar(currentSone.getImageByInternalId(avatarId).orNull()); for (Field field : fields) { String value = request.getHttpRequest().getPartAsStringFailsafe("field-" + field.getId(), 400); String filteredValue = filter(request.getHttpRequest().getHeader("Host"), value); diff --git a/src/main/java/net/pterodactylus/sone/web/WebInterface.java b/src/main/java/net/pterodactylus/sone/web/WebInterface.java index fbba8e0..95c8a3f 100644 --- a/src/main/java/net/pterodactylus/sone/web/WebInterface.java +++ b/src/main/java/net/pterodactylus/sone/web/WebInterface.java @@ -76,6 +76,7 @@ import net.pterodactylus.sone.main.ReparseFilter; import net.pterodactylus.sone.main.SonePlugin; import net.pterodactylus.sone.notify.ListNotification; import net.pterodactylus.sone.template.AlbumAccessor; +import net.pterodactylus.sone.template.BuildIdFilter; import net.pterodactylus.sone.template.CollectionAccessor; import net.pterodactylus.sone.template.CssClassNameFilter; import net.pterodactylus.sone.template.HttpRequestAccessor; @@ -285,6 +286,7 @@ public class WebInterface { templateContextFactory.addFilter("unique", new UniqueElementFilter()); templateContextFactory.addFilter("mod", new ModFilter()); templateContextFactory.addFilter("paginate", new PaginationFilter()); + templateContextFactory.addFilter("build-id", new BuildIdFilter()); templateContextFactory.addProvider(TemplateProvider.TEMPLATE_CONTEXT_PROVIDER); templateContextFactory.addProvider(new ClassPathTemplateProvider(WebInterface.class, "/templates/")); templateContextFactory.addTemplateObject("webInterface", this); diff --git a/src/main/resources/templates/editProfile.html b/src/main/resources/templates/editProfile.html index ddc08a9..af0bb8d 100644 --- a/src/main/resources/templates/editProfile.html +++ b/src/main/resources/templates/editProfile.html @@ -191,7 +191,7 @@ <%foreach currentSone.allImages image>
  • - checked="checked"<%/if>/> + checked="checked"<%/if>/>
    <% image|image-link max-width==48 max-height==48 mode==enlarge title=image.title>
  • <%/foreach> diff --git a/src/main/resources/templates/include/head.html b/src/main/resources/templates/include/head.html index 13b564d..74091ca 100644 --- a/src/main/resources/templates/include/head.html +++ b/src/main/resources/templates/include/head.html @@ -44,7 +44,7 @@ <%ifnull !currentSone> <%ifnull !currentSone.profile.avatar> - <%currentSone.profile.avatar|image-link max-width==80 max-height==80 mode==enlarge title=="Profile Avatar"> + <%currentSone.profile.avatar|build-id sone=currentSone|image-link max-width==80 max-height==80 mode==enlarge title=="Profile Avatar"> <%else> Profile Avatar <%/if> diff --git a/src/main/resources/templates/include/soneMenu.html b/src/main/resources/templates/include/soneMenu.html index fc51e79..a93b0a7 100644 --- a/src/main/resources/templates/include/soneMenu.html +++ b/src/main/resources/templates/include/soneMenu.html @@ -2,7 +2,7 @@