sone.getOptions().setShowNewPostNotifications(configuration.getBooleanValue(sonePrefix + "/Options/ShowNotification/NewPosts").getValue(true));
sone.getOptions().setShowNewReplyNotifications(configuration.getBooleanValue(sonePrefix + "/Options/ShowNotification/NewReplies").getValue(true));
sone.getOptions().setShowCustomAvatars(LoadExternalContent.valueOf(configuration.getStringValue(sonePrefix + "/Options/ShowCustomAvatars").getValue(LoadExternalContent.NEVER.name())));
+ sone.getOptions().setLoadLinkedImages(LoadExternalContent.valueOf(configuration.getStringValue(sonePrefix + "/Options/LoadLinkedImages").getValue(LoadExternalContent.NEVER.name())));
/* if we’re still here, Sone was loaded successfully. */
synchronized (sone) {
configuration.getBooleanValue(sonePrefix + "/Options/ShowNotification/NewPosts").setValue(sone.getOptions().isShowNewPostNotifications());
configuration.getBooleanValue(sonePrefix + "/Options/ShowNotification/NewReplies").setValue(sone.getOptions().isShowNewReplyNotifications());
configuration.getStringValue(sonePrefix + "/Options/ShowCustomAvatars").setValue(sone.getOptions().getShowCustomAvatars().name());
+ configuration.getStringValue(sonePrefix + "/Options/LoadLinkedImages").setValue(sone.getOptions().getLoadLinkedImages().name());
configuration.save();
import static net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.NEVER;
+import javax.annotation.Nonnull;
+
/**
* All Sone-specific options.
*
LoadExternalContent getShowCustomAvatars();
void setShowCustomAvatars(LoadExternalContent showCustomAvatars);
+ @Nonnull LoadExternalContent getLoadLinkedImages();
+ void setLoadLinkedImages(@Nonnull LoadExternalContent loadLinkedImages);
+
/**
* Possible values for all options that are related to loading external content.
*
private boolean showNewPostNotifications = true;
private boolean showNewReplyNotifications = true;
private LoadExternalContent showCustomAvatars = NEVER;
+ private LoadExternalContent loadLinkedImages = NEVER;
@Override
public boolean isAutoFollow() {
this.showCustomAvatars = showCustomAvatars;
}
+ @Nonnull
+ @Override
+ public LoadExternalContent getLoadLinkedImages() {
+ return loadLinkedImages;
+ }
+
+ @Override
+ public void setLoadLinkedImages(@Nonnull LoadExternalContent loadLinkedImages) {
+ this.loadLinkedImages = loadLinkedImages;
+ }
+
}
}
currentSone.getOptions().setShowNewReplyNotifications(showNotificationNewReplies);
String showCustomAvatars = request.getHttpRequest().getPartAsStringFailsafe("show-custom-avatars", 32);
currentSone.getOptions().setShowCustomAvatars(LoadExternalContent.valueOf(showCustomAvatars));
+ String loadLinkedImages = request.getHttpRequest().getPartAsStringFailsafe("load-linked-images", 32);
+ currentSone.getOptions().setLoadLinkedImages(LoadExternalContent.valueOf(loadLinkedImages));
webInterface.getCore().touchConfiguration();
}
Integer insertionDelay = parseInt(request.getHttpRequest().getPartAsStringFailsafe("insertion-delay", 16), null);
templateContext.set("show-notification-new-posts", currentSone.getOptions().isShowNewPostNotifications());
templateContext.set("show-notification-new-replies", currentSone.getOptions().isShowNewReplyNotifications());
templateContext.set("show-custom-avatars", currentSone.getOptions().getShowCustomAvatars().name());
+ templateContext.set("load-linked-images", currentSone.getOptions().getLoadLinkedImages().name());
}
templateContext.set("insertion-delay", preferences.getInsertionDelay());
templateContext.set("posts-per-page", preferences.getPostsPerPage());
import net.pterodactylus.sone.core.ElementLoader
import net.pterodactylus.sone.core.LinkedElement
+import net.pterodactylus.sone.data.Sone
+import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.ALWAYS
+import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.FOLLOWED
+import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.MANUALLY_TRUSTED
+import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.NEVER
+import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.TRUSTED
+import net.pterodactylus.sone.freenet.wot.OwnIdentity
import net.pterodactylus.sone.text.FreenetLinkPart
import net.pterodactylus.sone.text.Part
import net.pterodactylus.util.template.Filter
@Suppress("UNCHECKED_CAST")
override fun format(templateContext: TemplateContext?, data: Any?, parameters: MutableMap<String, Any?>?) =
- (data as? Iterable<Part>)
- ?.filterIsInstance<FreenetLinkPart>()
- ?.map { elementLoader.loadElement(it.link) }
- ?.filter { !it.failed }
- ?: listOf<LinkedElement>()
+ if (showLinkedImages(templateContext?.get("currentSone") as Sone?, parameters?.get("sone") as Sone?)) {
+ (data as? Iterable<Part>)
+ ?.filterIsInstance<FreenetLinkPart>()
+ ?.map { elementLoader.loadElement(it.link) }
+ ?.filter { !it.failed }
+ ?: listOf<LinkedElement>()
+ } else {
+ listOf<LinkedElement>()
+ }
+
+ private fun showLinkedImages(currentSone: Sone?, sone: Sone?): Boolean {
+ return (currentSone != null) && (sone != null) && ((currentSone == sone) || currentSoneAllowsImagesFromSone(currentSone, sone))
+ }
+
+ private fun currentSoneAllowsImagesFromSone(currentSone: Sone, externalSone: Sone) =
+ when (currentSone.options.loadLinkedImages) {
+ NEVER -> false
+ MANUALLY_TRUSTED -> externalSone.isLocal || currentSone.explicitelyTrusts(externalSone)
+ FOLLOWED -> externalSone.isLocal || currentSone.hasFriend(externalSone.id)
+ TRUSTED -> externalSone.isLocal || currentSone.implicitelyTrusts(externalSone)
+ ALWAYS -> true
+ }
+
+ private fun Sone.implicitelyTrusts(other: Sone): Boolean {
+ val explicitTrust = other.identity.getTrust(this.identity as OwnIdentity)?.explicit
+ val implicitTrust = other.identity.getTrust(this.identity as OwnIdentity)?.implicit
+ return ((explicitTrust != null) && (explicitTrust > 0)) || ((explicitTrust == null) && (implicitTrust != null) && (implicitTrust > 0))
+ }
+
+ private fun Sone.explicitelyTrusts(other: Sone) =
+ other.identity.getTrust(this.identity as OwnIdentity)?.explicit ?: -1 > 0
}
Page.Options.Option.ShowAvatars.ManuallyTrusted.Description=Nur benutzerdefinierte Avatare von Sones, denen Sie manuell einen Vertrauenswert von mehr als 0 zugewiesen haben, anzeigen.
Page.Options.Option.ShowAvatars.Trusted.Description=Nur benutzerdefinierte Avatare von Sones, die einen berechneten Vertrauenswert von mehr als 0 haben, anzeigen.
Page.Options.Option.ShowAvatars.Always.Description=Immer benutzerdefinierte Avatare anzeigen. Warnung: Benutzerdefinierte Avatare können beliebiges Bildmaterial enthalten!
+Page.Options.Section.LoadLinkedImagesOptions.Title=Verlinkte Bilder laden
+Page.Options.Option.LoadLinkedImages.Description=Sone kann automatisch in Nachrichten und Antworten verlinkte Bilder laden. Diese Bilder werden nur aus Freenet geladen, niemals aus dem Internet!
+Page.Options.Option.LoadLinkedImages.Never.Description=Niemals verlinkte Bilder laden.
+Page.Options.Option.LoadLinkedImages.Followed.Description=Nur Bilder aus Nachrichten von Sones, denen Sie folgen, laden.
+Page.Options.Option.LoadLinkedImages.ManuallyTrusted.Description=Nur Bilder aus Nachrichten von Sones, denen Sie manuell einen Vertrauenswert von mehr als 0 zugewiesen haben, laden.
+Page.Options.Option.LoadLinkedImages.Trusted.Description=Nur Bilder aus Nachrichten von Sones, die einen berechneten Vertrauenswert von mehr als 0 haben, laden.
+Page.Options.Option.LoadLinkedImages.Always.Description=Immer verlinkte Bilder laden. Warnung: Verlinkte Bilder können beliebiges Bildmaterial enthalten!
Page.Options.Section.RuntimeOptions.Title=Laufzeitverhalten
Page.Options.Option.InsertionDelay.Description=Anzahl der Sekunden, die vor dem Hochladen einer Sone nach einer Änderung gewartet wird.
Page.Options.Option.PostsPerPage.Description=Anzahl der Nachrichten pro Seite.
Page.Options.Option.ShowAvatars.ManuallyTrusted.Description=Only show avatars for Sones that you have manually assigned a trust value larger than 0 to.
Page.Options.Option.ShowAvatars.Trusted.Description=Only show avatars for Sones that have a trust value larger than 0.
Page.Options.Option.ShowAvatars.Always.Description=Always show custom avatars. Be warned: some avatars might contain disturbing or offensive imagery.
+Page.Options.Section.LoadLinkedImagesOptions.Title=Load Linked Images
+Page.Options.Option.LoadLinkedImages.Description=Sone can automatically try to load images that are linked to in posts and replies. This will only ever load images from Freenet, never from the internet!
+Page.Options.Option.LoadLinkedImages.Never.Description=Never load linked images.
+Page.Options.Option.LoadLinkedImages.Followed.Description=Only load images linked from Sones that you follow.
+Page.Options.Option.LoadLinkedImages.ManuallyTrusted.Description=Only load images linked from Sones that you have manually assigned a trust value larger than 0 to.
+Page.Options.Option.LoadLinkedImages.Trusted.Description=Only load images linked from Sones that have a trust value larger than 0.
+Page.Options.Option.LoadLinkedImages.Always.Description=Always load linked images. Be warned: some images might be disturbing or considered offensive.
Page.Options.Section.RuntimeOptions.Title=Runtime Behaviour
Page.Options.Option.InsertionDelay.Description=The number of seconds the Sone inserter waits after a modification of a Sone before it is being inserted.
Page.Options.Option.PostsPerPage.Description=The number of posts to display on a page before pagination controls are being shown.
Page.Options.Option.ShowAvatars.ManuallyTrusted.Description=Solo mostrar avatares de Sones a los que has asignado manualmente un valor de veracidad mayor que 0.
Page.Options.Option.ShowAvatars.Trusted.Description=Solo mostrar avatares para Sones que tienen un valor de veracidad mayor que 0.
Page.Options.Option.ShowAvatars.Always.Description=Mostrar siempre avatares customizados. Advertencia, algunos avatares pueden contener imágenes perturbadoras o ofensivas.
+Page.Options.Section.LoadLinkedImagesOptions.Title=Load Linked Images
+Page.Options.Option.LoadLinkedImages.Description=Sone can automatically try to load images that are linked to in posts and replies. This will only ever load images from Freenet, never from the internet!
+Page.Options.Option.LoadLinkedImages.Never.Description=Never load linked images.
+Page.Options.Option.LoadLinkedImages.Followed.Description=Only load images linked from Sones that you follow.
+Page.Options.Option.LoadLinkedImages.ManuallyTrusted.Description=Only load images linked from Sones that you have manually assigned a trust value larger than 0 to.
+Page.Options.Option.LoadLinkedImages.Trusted.Description=Only load images linked from Sones that have a trust value larger than 0.
+Page.Options.Option.LoadLinkedImages.Always.Description=Always load linked images. Be warned: some images might be disturbing or considered offensive.
Page.Options.Section.RuntimeOptions.Title=Comportamiento de la ejecución.
Page.Options.Option.InsertionDelay.Description=Número de segundos que se esperarán para insertar el Sone tras una modificación.
Page.Options.Option.PostsPerPage.Description=Número de publicaciones que se mostrarán en una página antes de que se muestren los controles de navegación.
Notification.SoneIsInserting.Text=Tu Sone sone://{0} está siendo insertado.
Notification.SoneIsInserted.Text=Tu Sone sone://{0} ha sido insertado en {1,number} {1,choice,0#segundos|1#segundo|1<segundos}.
Notification.SoneInsertAborted.Text=Tu Sone sone://{0} no pudo ser insertado.
+# 55-61
Page.Options.Option.ShowAvatars.ManuallyTrusted.Description=Ne montrer que les avatars des Sones auxquelles vous êtes assignés manuellement une confiance superieure à 0.
Page.Options.Option.ShowAvatars.Trusted.Description=Ne montrer que les avatars des Sones qui ont une confiance superieure à 0.
Page.Options.Option.ShowAvatars.Always.Description=Montre tout le temps les avatars personnalisés. Attention: certains avatars peuvent être offensants !
+Page.Options.Section.LoadLinkedImagesOptions.Title=Load Linked Images
+Page.Options.Option.LoadLinkedImages.Description=Sone can automatically try to load images that are linked to in posts and replies. This will only ever load images from Freenet, never from the internet!
+Page.Options.Option.LoadLinkedImages.Never.Description=Never load linked images.
+Page.Options.Option.LoadLinkedImages.Followed.Description=Only load images linked from Sones that you follow.
+Page.Options.Option.LoadLinkedImages.ManuallyTrusted.Description=Only load images linked from Sones that you have manually assigned a trust value larger than 0 to.
+Page.Options.Option.LoadLinkedImages.Trusted.Description=Only load images linked from Sones that have a trust value larger than 0.
+Page.Options.Option.LoadLinkedImages.Always.Description=Always load linked images. Be warned: some images might be disturbing or considered offensive.
Page.Options.Section.RuntimeOptions.Title=Comportement runtime
Page.Options.Option.InsertionDelay.Description=Le délai d'insertion d'un Sone.
Page.Options.Option.PostsPerPage.Description=Le nombre de message à afficher par page avant que les boutons de pagination soit affichés.
Notification.SoneIsInserting.Text=Votre Sone sone://{0} va maintenant être inséré.
Notification.SoneIsInserted.Text=votre Sone sone://{0} a été inséré dans {1,number} {1,choice,0#seconds|1#second|1<seconds}.
Notification.SoneInsertAborted.Text=Votre Sone sone://{0} ne peut pas être inséré.
+# 55-61
Page.Options.Option.ShowAvatars.ManuallyTrusted.Description=信用値を手動で0以上に設定しているSoneのみ、カスタムアイコンを表示する。
Page.Options.Option.ShowAvatars.Trusted.Description=信用値が0以上のSoneのみ、カスタムアイコンを表示する。
Page.Options.Option.ShowAvatars.Always.Description=常にカスタムアイコンを表示する。注意:不快な画像が表示される可能性があります。
+Page.Options.Section.LoadLinkedImagesOptions.Title=Load Linked Images
+Page.Options.Option.LoadLinkedImages.Description=Sone can automatically try to load images that are linked to in posts and replies. This will only ever load images from Freenet, never from the internet!
+Page.Options.Option.LoadLinkedImages.Never.Description=Never load linked images.
+Page.Options.Option.LoadLinkedImages.Followed.Description=Only load images linked from Sones that you follow.
+Page.Options.Option.LoadLinkedImages.ManuallyTrusted.Description=Only load images linked from Sones that you have manually assigned a trust value larger than 0 to.
+Page.Options.Option.LoadLinkedImages.Trusted.Description=Only load images linked from Sones that have a trust value larger than 0.
+Page.Options.Option.LoadLinkedImages.Always.Description=Always load linked images. Be warned: some images might be disturbing or considered offensive.
Page.Options.Section.RuntimeOptions.Title=実行の挙動
Page.Options.Option.InsertionDelay.Description=Soneを変更した後にインサートが開始されるまでの遅延時間(秒)。
Page.Options.Option.PostsPerPage.Description=ページ送りのボタンが表示されるまでに表示する投稿の数。
Notification.SoneIsInserting.Text=あなたのSone sone://{0}は現在インサート中です。
Notification.SoneIsInserted.Text=あなたのSone sone://{0}は{1,number}{1,choice,0#秒|1#秒|1<秒}でインサートされました。
Notification.SoneInsertAborted.Text=あなたのSone sone://{0}のインサートに失敗しました。
-# 60, 100, 458
+# 55-51, 67, 107, 465
Page.Options.Option.ShowAvatars.ManuallyTrusted.Description=Bare vis avatar for Soner du manuelt har gitt en tillit større en 0.
Page.Options.Option.ShowAvatars.Trusted.Description=Bare vis avatar for Soner som har en tillit større enn 0.
Page.Options.Option.ShowAvatars.Always.Description=Alltid vis egendefinerte avatarer. Advarsel: Noen avatarer kan inneholde forstyrrende eller provoserende bilder.
+Page.Options.Section.LoadLinkedImagesOptions.Title=Load Linked Images
+Page.Options.Option.LoadLinkedImages.Description=Sone can automatically try to load images that are linked to in posts and replies. This will only ever load images from Freenet, never from the internet!
+Page.Options.Option.LoadLinkedImages.Never.Description=Never load linked images.
+Page.Options.Option.LoadLinkedImages.Followed.Description=Only load images linked from Sones that you follow.
+Page.Options.Option.LoadLinkedImages.ManuallyTrusted.Description=Only load images linked from Sones that you have manually assigned a trust value larger than 0 to.
+Page.Options.Option.LoadLinkedImages.Trusted.Description=Only load images linked from Sones that have a trust value larger than 0.
+Page.Options.Option.LoadLinkedImages.Always.Description=Always load linked images. Be warned: some images might be disturbing or considered offensive.
Page.Options.Section.RuntimeOptions.Title=Oppførsel ved kjøretid
Page.Options.Option.InsertionDelay.Description=Antall sekunder Sone-innsetteren skal vente etter en endring av en Sone før den blir innsatt.
Page.Options.Option.PostsPerPage.Description=Antallet innlegg å vise pr side før side-kontroller blir vist.
Notification.SoneIsInserting.Text=Your Sone sone://{0} is now being inserted.
Notification.SoneIsInserted.Text=Your Sone sone://{0} has been inserted in {1,number} {1,choice,0#seconds|1#second|1<seconds}.
Notification.SoneInsertAborted.Text=Your Sone sone://{0} could not be inserted.
-# 60, 100, 120-121, 308-310, 312-314, 458, 463-465
+# 55-61, 67, 107, 127-128, 315-317, 319-321, 465, 471-473
Page.Options.Option.ShowAvatars.ManuallyTrusted.Description=Pokazuj avatary tylko tych użytkowników Sone, którym ręcznie przyznałeś ilość punktów zaufania przekraczającą 0.
Page.Options.Option.ShowAvatars.Trusted.Description=Pokazuj avatary tylko tych użytkowników Sone, którzy mają ilość punktów zaufania większą niż 0.
Page.Options.Option.ShowAvatars.Always.Description=Zawsze pokazuj niestandardowe avatary. Uwaga: niektóre avatary mogą zawierać obraźliwe treści.
+Page.Options.Section.LoadLinkedImagesOptions.Title=Load Linked Images
+Page.Options.Option.LoadLinkedImages.Description=Sone can automatically try to load images that are linked to in posts and replies. This will only ever load images from Freenet, never from the internet!
+Page.Options.Option.LoadLinkedImages.Never.Description=Never load linked images.
+Page.Options.Option.LoadLinkedImages.Followed.Description=Only load images linked from Sones that you follow.
+Page.Options.Option.LoadLinkedImages.ManuallyTrusted.Description=Only load images linked from Sones that you have manually assigned a trust value larger than 0 to.
+Page.Options.Option.LoadLinkedImages.Trusted.Description=Only load images linked from Sones that have a trust value larger than 0.
+Page.Options.Option.LoadLinkedImages.Always.Description=Always load linked images. Be warned: some images might be disturbing or considered offensive.
Page.Options.Section.RuntimeOptions.Title=Tryb pracy
Page.Options.Option.InsertionDelay.Description=Czas oczekiwania użytkownika Sone na modifikację profilu Sone przed jego załadowaniem.
Page.Options.Option.PostsPerPage.Description=Ilość postów wyświetlanych na stronie przed pojawieniem się znaków paginacji.
Notification.SoneIsInserting.Text=Twoje Sone sone://{0} jest w tej chili wysyłane.
Notification.SoneIsInserted.Text=Twoje sone://{0} zostało wysłane w {1,number} {1,choice,0#seconds|1#second|1<seconds}.
Notification.SoneInsertAborted.Text=Twoje Sone sone://{0} nie mogło zostać wysłane.
-# 458
+# 55-61, 465
Page.Options.Option.ShowAvatars.ManuallyTrusted.Description=Показывать аватары только для Sone, которым вы вручную задали значение доверия выше 0.
Page.Options.Option.ShowAvatars.Trusted.Description=Показывать аватары только для Sone, значение доверия которых выше 0.
Page.Options.Option.ShowAvatars.Always.Description=Всегда показывать пользовательские аватары. Предупреждение: некоторые аватары могут содержать раздражающие или оскорбительные изображения.
+Page.Options.Section.LoadLinkedImagesOptions.Title=Load Linked Images
+Page.Options.Option.LoadLinkedImages.Description=Sone can automatically try to load images that are linked to in posts and replies. This will only ever load images from Freenet, never from the internet!
+Page.Options.Option.LoadLinkedImages.Never.Description=Never load linked images.
+Page.Options.Option.LoadLinkedImages.Followed.Description=Only load images linked from Sones that you follow.
+Page.Options.Option.LoadLinkedImages.ManuallyTrusted.Description=Only load images linked from Sones that you have manually assigned a trust value larger than 0 to.
+Page.Options.Option.LoadLinkedImages.Trusted.Description=Only load images linked from Sones that have a trust value larger than 0.
+Page.Options.Option.LoadLinkedImages.Always.Description=Always load linked images. Be warned: some images might be disturbing or considered offensive.
Page.Options.Section.RuntimeOptions.Title=Поведение во время работы.
Page.Options.Option.InsertionDelay.Description=Количество секунд, в течение которых выгрузчик Sone ожидает после изменения Sone до того, как он будет выгружен.
Page.Options.Option.PostsPerPage.Description=Количество сообщений, которое должно быть показно на странице до того, как будут показаны кнопки переключения страниц.
Notification.SoneIsInserting.Text=Your Sone sone://{0} is now being inserted.
Notification.SoneIsInserted.Text=Your Sone sone://{0} has been inserted in {1,number} {1,choice,0#seconds|1#second|1<seconds}.
Notification.SoneInsertAborted.Text=Your Sone sone://{0} could not be inserted.
-# 60, 100, 120-121, 308-310, 312-314, 458, 463-465
+# 55-61, 67, 107, 127-128, 315-317, 319-321, 465, 471-473
<div class="post-text short-text<%if raw> hidden<%/if><%if shortText|match key=renderedText> hidden<%/if>"><% shortText></div>
<%if !shortText|match value=renderedText><%if !raw><a class="expand-post-text" href="viewPost.html?post=<% post.id|html>&raw=true"><%= View.Post.ShowMore|l10n|html></a><%/if><%/if>
<%if !shortText|match value=renderedText><%if !raw><a class="shrink-post-text hidden"><%= View.Post.ShowLess|l10n|html></a><%/if><%/if>
- <% parsedText|linked-elements|store key==linkedElements>
+ <% parsedText|linked-elements sone=post.sone|store key==linkedElements>
<% foreach linkedElements linkedElement>
<% first>
<div class="linked-elements">
<div class="reply-text short-text<%if raw> hidden<%/if><%if shortText|match key=renderedText> hidden<%/if>"><% shortText></div>
<%if !shortText|match value=renderedText><%if !raw><a class="expand-reply-text" href="viewPost.html?post=<% reply.postId|html>&raw=true"><%= View.Post.ShowMore|l10n|html></a><%/if><%/if>
<%if !shortText|match value=renderedText><%if !raw><a class="shrink-reply-text hidden"><%= View.Post.ShowLess|l10n|html></a><%/if><%/if>
- <% parsedText|linked-elements|store key==linkedElements>
+ <% parsedText|linked-elements sone=reply.sone|store key==linkedElements>
<% foreach linkedElements linkedElement>
<% first>
<div class="linked-elements">
</li>
</ul>
+ <h2><%= Page.Options.Section.LoadLinkedImagesOptions.Title|l10n|html></h2>
+
+ <p><%= Page.Options.Option.LoadLinkedImages.Description|l10n|html></p>
+
+ <ul>
+ <li>
+ <input type="radio" name="load-linked-images" value="NEVER"<%if load-linked-images|match value==NEVER> checked="checked"<%/if>/>
+ <%=Page.Options.Option.LoadLinkedImages.Never.Description|l10n|html>
+ </li>
+ <li>
+ <input type="radio" name="load-linked-images" value="FOLLOWED"<%if load-linked-images|match value==FOLLOWED> checked="checked"<%/if>/>
+ <%=Page.Options.Option.LoadLinkedImages.Followed.Description|l10n|html>
+ </li>
+ <li>
+ <input type="radio" name="load-linked-images" value="MANUALLY_TRUSTED"<%if load-linked-images|match value==MANUALLY_TRUSTED> checked="checked"<%/if>/>
+ <%=Page.Options.Option.LoadLinkedImages.ManuallyTrusted.Description|l10n|html>
+ </li>
+ <li>
+ <input type="radio" name="load-linked-images" value="TRUSTED"<%if load-linked-images|match value==TRUSTED> checked="checked"<%/if>/>
+ <%=Page.Options.Option.LoadLinkedImages.Trusted.Description|l10n|html>
+ </li>
+ <li>
+ <input type="radio" name="load-linked-images" value="ALWAYS"<%if load-linked-images|match value==ALWAYS> checked="checked"<%/if>/>
+ <%=Page.Options.Option.LoadLinkedImages.Always.Description|l10n|html>
+ </li>
+ </ul>
+
<h2><%= Page.Options.Section.RuntimeOptions.Title|l10n|html></h2>
<p><%= Page.Options.Option.InsertionDelay.Description|l10n|html></p>
Post post3 = createPost(true, 2000L);
Set<Post> bookmarkedPosts = createBookmarkedPosts(post1, post2, post3);
when(core.getBookmarkedPosts()).thenReturn(bookmarkedPosts);
- when(core.getPreferences().getPostsPerPage()).thenReturn(5);
+ core.getPreferences().setPostsPerPage(5);
page.processTemplate(freenetRequest, templateContext);
assertThat((Collection<Post>) templateContext.get("posts"), contains(post1, post3, post2));
assertThat(((Pagination<Post>) templateContext.get("pagination")).getItems(), contains(post1, post3, post2));
Post post3 = createPost(false, 2000L);
Set<Post> bookmarkedPosts = createBookmarkedPosts(post1, post2, post3);
when(core.getBookmarkedPosts()).thenReturn(bookmarkedPosts);
- when(core.getPreferences().getPostsPerPage()).thenReturn(5);
+ core.getPreferences().setPostsPerPage(5);
page.processTemplate(freenetRequest, templateContext);
assertThat((Collection<Post>) templateContext.get("posts"), contains(post2, post1));
assertThat(((Pagination<Post>) templateContext.get("pagination")).getItems(), contains(post2, post1));
@Test
public void doNotShowCreateSoneInMenuIfFullAccessRequiredButClientHasNoFullAccess() {
- when(core.getPreferences().isRequireFullAccess()).thenReturn(true);
+ core.getPreferences().setRequireFullAccess(true);
when(toadletContext.isAllowedFullAccess()).thenReturn(false);
assertThat(page.isEnabled(toadletContext), is(false));
}
@Test
public void showCreateSoneInMenuIfNotLoggedInAndClientHasFullAccess() {
- when(core.getPreferences().isRequireFullAccess()).thenReturn(true);
+ core.getPreferences().setRequireFullAccess(true);
when(toadletContext.isAllowedFullAccess()).thenReturn(true);
unsetCurrentSone();
assertThat(page.isEnabled(toadletContext), is(true));
@Before
public void setupNumberOfPostsPerPage() {
- when(webInterface.getCore().getPreferences().getPostsPerPage()).thenReturn(5);
+ webInterface.getCore().getPreferences().setPostsPerPage(5);
}
@Test
import java.util.Set;
import net.pterodactylus.sone.core.Core;
+import net.pterodactylus.sone.core.Preferences;
import net.pterodactylus.sone.core.UpdateChecker;
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.data.SoneOptions.DefaultSoneOptions;
import net.pterodactylus.sone.freenet.wot.OwnIdentity;
import net.pterodactylus.sone.web.page.FreenetRequest;
import net.pterodactylus.util.notify.Notification;
import freenet.support.api.HTTPRequest;
import com.google.common.base.Optional;
+import com.google.common.eventbus.EventBus;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.ExpectedException;
protected final Template template = new Template();
protected final WebInterface webInterface = mock(WebInterface.class, RETURNS_DEEP_STUBS);
+ protected final EventBus eventBus = mock(EventBus.class);
protected final Core core = webInterface.getCore();
protected final Sone currentSone = mock(Sone.class);
public final void setupCore() {
UpdateChecker updateChecker = mock(UpdateChecker.class);
when(core.getUpdateChecker()).thenReturn(updateChecker);
+ when(core.getPreferences()).thenReturn(new Preferences(eventBus));
when(core.getLocalSone(anyString())).thenReturn(null);
when(core.getLocalSones()).thenReturn(localSones);
when(core.getSone(anyString())).thenReturn(Optional.<Sone>absent());
when(webInterface.getNotifications(currentSone)).thenReturn(new ArrayList<Notification>());
}
+ @Before
+ public void setupSone() {
+ when(currentSone.getOptions()).thenReturn(new DefaultSoneOptions());
+ }
+
protected void unsetCurrentSone() {
when(webInterface.getCurrentSone(toadletContext)).thenReturn(null);
when(webInterface.getCurrentSone(eq(toadletContext), anyBoolean())).thenReturn(null);
import net.pterodactylus.sone.core.ElementLoader
import net.pterodactylus.sone.core.LinkedElement
+import net.pterodactylus.sone.data.Sone
+import net.pterodactylus.sone.data.SoneOptions.DefaultSoneOptions
+import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.ALWAYS
+import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.FOLLOWED
+import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.MANUALLY_TRUSTED
+import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.TRUSTED
+import net.pterodactylus.sone.freenet.wot.OwnIdentity
+import net.pterodactylus.sone.freenet.wot.Trust
import net.pterodactylus.sone.test.mock
import net.pterodactylus.sone.text.FreenetLinkPart
import net.pterodactylus.sone.text.LinkPart
+import net.pterodactylus.sone.text.Part
import net.pterodactylus.sone.text.PlainTextPart
+import net.pterodactylus.util.template.TemplateContext
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.contains
+import org.hamcrest.Matchers.emptyIterable
+import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.`when`
private val imageLoader = mock<ElementLoader>()
private val filter = LinkedElementsFilter(imageLoader)
+ private val templateContext = TemplateContext()
+ private val parameters = mutableMapOf<String, Any?>()
+ private val sone = createSone()
+ private val remoteSone = createSone("remote-id")
+ private val parts: List<Part> = listOf(
+ PlainTextPart("text"),
+ LinkPart("http://link", "link"),
+ FreenetLinkPart("KSK@link", "link", false),
+ FreenetLinkPart("KSK@loading.png", "link", false),
+ FreenetLinkPart("KSK@link.png", "link", false)
+ )
- @Test
- fun `filter finds all loaded freenet images`() {
- val parts = listOf(
- PlainTextPart("text"),
- LinkPart("http://link", "link"),
- FreenetLinkPart("KSK@link", "link", false),
- FreenetLinkPart("KSK@loading.png", "link", false),
- FreenetLinkPart("KSK@link.png", "link", false)
- )
+ @Before
+ fun setupSone() {
+ `when`(sone.options).thenReturn(DefaultSoneOptions())
+ }
+
+ @Before
+ fun setupImageLoader() {
`when`(imageLoader.loadElement("KSK@link")).thenReturn(LinkedElement("KSK@link", failed = true))
`when`(imageLoader.loadElement("KSK@loading.png")).thenReturn(LinkedElement("KSK@loading.png", loading = true))
`when`(imageLoader.loadElement("KSK@link.png")).thenReturn(LinkedElement("KSK@link.png"))
- val loadedImages = filter.format(null, parts, null)
+ }
+
+ @Test
+ fun `filter does not find any image if there is no template context`() {
+ assertThat(filter.format(null, parts, parameters), emptyIterable())
+ }
+
+ @Test
+ fun `filter does not find any image if there is no current sone`() {
+ verifyThatImagesAreNotPresent()
+ }
+
+ @Test
+ fun `filter does not find any images if there is no remote sone`() {
+ sone.options.loadLinkedImages = ALWAYS
+ templateContext.set("currentSone", sone)
+ verifyThatImagesAreNotPresent()
+ }
+
+ @Test
+ fun `filter does not find any images if sone does not allow to load images`() {
+ templateContext.set("currentSone", sone)
+ parameters["sone"] = remoteSone
+ verifyThatImagesAreNotPresent()
+ }
+
+ @Test
+ fun `filter finds all loaded freenet images from the sone itself`() {
+ templateContext.set("currentSone", sone)
+ parameters["sone"] = sone
+ verifyThatImagesArePresent()
+ }
+
+ @Test
+ fun `filter finds images if the remote sone is local`() {
+ sone.options.loadLinkedImages = MANUALLY_TRUSTED
+ templateContext.set("currentSone", sone)
+ `when`(remoteSone.isLocal).thenReturn(true)
+ parameters["sone"] = remoteSone
+ verifyThatImagesArePresent()
+ }
+
+ @Test
+ fun `filter does not find images if local sone requires manual trust and remote sone has not trust`() {
+ sone.options.loadLinkedImages = MANUALLY_TRUSTED
+ templateContext.set("currentSone", sone)
+ parameters["sone"] = remoteSone
+ verifyThatImagesAreNotPresent()
+ }
+
+ @Test
+ fun `filter does not find images if local sone requires manual trust and remote sone has only implicit trust`() {
+ sone.options.loadLinkedImages = MANUALLY_TRUSTED
+ templateContext.set("currentSone", sone)
+ `when`(remoteSone.identity.getTrust(this.sone.identity as OwnIdentity)).thenReturn(Trust(null, 100, null))
+ parameters["sone"] = remoteSone
+ verifyThatImagesAreNotPresent()
+ }
+
+ @Test
+ fun `filter does not find images if local sone requires manual trust and remote sone has explicit trust of zero`() {
+ sone.options.loadLinkedImages = MANUALLY_TRUSTED
+ templateContext.set("currentSone", sone)
+ `when`(remoteSone.identity.getTrust(this.sone.identity as OwnIdentity)).thenReturn(Trust(0, null, null))
+ parameters["sone"] = remoteSone
+ verifyThatImagesAreNotPresent()
+ }
+
+ @Test
+ fun `filter finds images if local sone requires manual trust and remote sone has explicit trust of one`() {
+ sone.options.loadLinkedImages = MANUALLY_TRUSTED
+ templateContext.set("currentSone", sone)
+ `when`(remoteSone.identity.getTrust(this.sone.identity as OwnIdentity)).thenReturn(Trust(1, null, null))
+ parameters["sone"] = remoteSone
+ verifyThatImagesArePresent()
+ }
+
+ @Test
+ fun `filter does not find images if local sone requires following and remote sone is not followed`() {
+ sone.options.loadLinkedImages = FOLLOWED
+ templateContext["currentSone"] = sone
+ parameters["sone"] = remoteSone
+ verifyThatImagesAreNotPresent()
+ }
+
+ @Test
+ fun `filter finds images if local sone requires following and remote sone is followed`() {
+ sone.options.loadLinkedImages = FOLLOWED
+ `when`(sone.hasFriend("remote-id")).thenReturn(true)
+ templateContext["currentSone"] = sone
+ parameters["sone"] = remoteSone
+ verifyThatImagesArePresent()
+ }
+
+ @Test
+ fun `filter finds images if local sone requires following and remote sone is the same as the local sone`() {
+ sone.options.loadLinkedImages = FOLLOWED
+ templateContext["currentSone"] = sone
+ parameters["sone"] = sone
+ verifyThatImagesArePresent()
+ }
+
+ @Test
+ fun `filter finds images if following is required and remote sone is a local sone`() {
+ sone.options.loadLinkedImages = FOLLOWED
+ templateContext["currentSone"] = sone
+ `when`(remoteSone.isLocal).thenReturn(true)
+ parameters["sone"] = remoteSone
+ verifyThatImagesArePresent()
+ }
+
+ @Test
+ fun `filter does not find images if any trust is required and remote sone does not have any trust`() {
+ sone.options.loadLinkedImages = TRUSTED
+ templateContext["currentSone"] = sone
+ parameters["sone"] = remoteSone
+ verifyThatImagesAreNotPresent()
+ }
+
+ @Test
+ fun `filter does not find images if any trust is required and remote sone has implicit trust of zero`() {
+ sone.options.loadLinkedImages = TRUSTED
+ templateContext["currentSone"] = sone
+ `when`(remoteSone.identity.getTrust(sone.identity as OwnIdentity)).thenReturn(Trust(null, 0, null))
+ parameters["sone"] = remoteSone
+ verifyThatImagesAreNotPresent()
+ }
+
+ @Test
+ fun `filter finds images if any trust is required and remote sone has implicit trust of one`() {
+ sone.options.loadLinkedImages = TRUSTED
+ templateContext["currentSone"] = sone
+ `when`(remoteSone.identity.getTrust(sone.identity as OwnIdentity)).thenReturn(Trust(null, 1, null))
+ parameters["sone"] = remoteSone
+ verifyThatImagesArePresent()
+ }
+
+ @Test
+ fun `filter does not find images if any trust is required and remote sone has explicit trust of zero but implicit trust of one`() {
+ sone.options.loadLinkedImages = TRUSTED
+ templateContext["currentSone"] = sone
+ `when`(remoteSone.identity.getTrust(sone.identity as OwnIdentity)).thenReturn(Trust(0, 1, null))
+ parameters["sone"] = remoteSone
+ verifyThatImagesAreNotPresent()
+ }
+
+ @Test
+ fun `filter finds images if any trust is required and remote sone has explicit trust of one but no implicit trust`() {
+ sone.options.loadLinkedImages = TRUSTED
+ templateContext["currentSone"] = sone
+ `when`(remoteSone.identity.getTrust(sone.identity as OwnIdentity)).thenReturn(Trust(1, null, null))
+ parameters["sone"] = remoteSone
+ verifyThatImagesArePresent()
+ }
+
+ @Test
+ fun `filter finds images if any trust is required and remote sone is a local sone`() {
+ sone.options.loadLinkedImages = TRUSTED
+ templateContext["currentSone"] = sone
+ `when`(remoteSone.isLocal).thenReturn(true)
+ parameters["sone"] = remoteSone
+ verifyThatImagesArePresent()
+ }
+
+ @Test
+ fun `filter finds images if no trust is required`() {
+ sone.options.loadLinkedImages = ALWAYS
+ templateContext["currentSone"] = sone
+ parameters["sone"] = remoteSone
+ verifyThatImagesArePresent()
+ }
+
+ private fun verifyThatImagesArePresent() {
+ val loadedImages = filter.format(templateContext, parts, parameters)
assertThat(loadedImages, contains<LinkedElement>(
LinkedElement("KSK@loading.png", failed = false, loading = true),
LinkedElement("KSK@link.png", failed = false, loading = false)
))
}
+ private fun verifyThatImagesAreNotPresent() {
+ assertThat(filter.format(templateContext, parts, parameters), emptyIterable())
+ }
+
+ private fun createSone(id: String = "sone-id"): Sone {
+ val sone = mock<Sone>()
+ `when`(sone.id).thenReturn(id)
+ `when`(sone.options).thenReturn(DefaultSoneOptions())
+ `when`(sone.identity).thenReturn(mock<OwnIdentity>())
+ return sone
+ }
+
}
--- /dev/null
+package net.pterodactylus.sone.web
+
+import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.ALWAYS
+import net.pterodactylus.sone.web.WebTestUtils.redirectsTo
+import net.pterodactylus.util.web.Method.POST
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.Matchers.`is`
+import org.junit.Test
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+/**
+ * Unit test for [OptionsPage].
+ */
+class OptionsPageTest : WebPageTest() {
+
+ private val page = OptionsPage(template, webInterface)
+
+ @Test
+ fun `options page sets correct value for load-linked-images`() {
+ request("", POST)
+ addHttpRequestParameter("show-custom-avatars", "ALWAYS")
+ addHttpRequestParameter("load-linked-images", "ALWAYS")
+ expectedException.expect(redirectsTo("options.html"))
+ try {
+ page.handleRequest(freenetRequest, templateContext)
+ } finally {
+ assertThat(currentSone.options.loadLinkedImages, `is`(ALWAYS))
+ verify(core, times(2)).touchConfiguration()
+ }
+ }
+
+}