/** The Sone downloader. */
private SoneDownloader soneDownloader;
+ /** The Sone blacklist. */
+ private final Set<Sone> blacklistedSones = new HashSet<Sone>();
+
/** The local Sones. */
private final Set<Sone> localSones = new HashSet<Sone>();
* @return The local Sones
*/
public Set<Sone> getSones() {
- return Collections.unmodifiableSet(localSones);
+ return Filters.filteredSet(localSones, new Filter<Sone>() {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public boolean filterObject(Sone sone) {
+ return !blacklistedSones.contains(sone);
+ }
+ });
}
/**
* @return All known sones
*/
public Collection<Sone> getKnownSones() {
- return soneCache.values();
+ return Filters.filteredCollection(soneCache.values(), new Filter<Sone>() {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public boolean filterObject(Sone sone) {
+ return !blacklistedSones.contains(sone);
+ }
+ });
}
/**
@Override
@SuppressWarnings("synthetic-access")
- public boolean filterObject(Sone object) {
- return !localSones.contains(object);
+ public boolean filterObject(Sone sone) {
+ return !blacklistedSones.contains(sone) && !localSones.contains(sone);
}
});
}
/**
+ * Returns all blacklisted Sones.
+ *
+ * @return All blacklisted Sones
+ */
+ public Collection<Sone> getBlacklistedSones() {
+ return Collections.unmodifiableCollection(blacklistedSones);
+ }
+
+ /**
+ * Checks whether the given Sone is blacklisted.
+ *
+ * @param sone
+ * The Sone to check
+ * @return {@code true} if this Sone is blacklisted, {@code false} otherwise
+ */
+ public boolean isBlacklistedSone(Sone sone) {
+ return blacklistedSones.contains(sone);
+ }
+
+ /**
* Returns the status of the given Sone.
*
* @param sone
}
/**
+ * Blackslists the given Sone.
+ *
+ * @param sone
+ * The Sone to blacklist
+ */
+ public void blacklistSone(Sone sone) {
+ if (blacklistedSones.add(sone)) {
+ soneDownloader.removeSone(sone);
+ if (localSones.remove(sone)) {
+ SoneInserter soneInserter = soneInserters.remove(sone);
+ soneInserter.stop();
+ }
+ }
+ }
+
+ /**
+ * Unblacklists the given Sone.
+ *
+ * @param sone
+ * The Sone to unblacklist
+ */
+ public void unblacklistSone(Sone sone) {
+ if (blacklistedSones.remove(sone)) {
+ if (sone.getInsertUri() != null) {
+ addLocalSone(sone);
+ } else {
+ addSone(sone);
+ }
+ }
+ }
+
+ /**
* Creates a new Sone at a random location.
*
* @param name
}
}
+ /* load all blacklisted Sones. */
+ int blacklistedSonesCounter = 0;
+ while (true) {
+ String blacklistedSonePrefix = "BlacklistedSone." + blacklistedSonesCounter++;
+ String blacklistedSoneId = configuration.getStringValue(blacklistedSonePrefix + "/ID").getValue(null);
+ if (blacklistedSoneId == null) {
+ break;
+ }
+ String blacklistedSoneName = configuration.getStringValue(blacklistedSonePrefix + "/Name").getValue(null);
+ String blacklistedSoneKey = configuration.getStringValue(blacklistedSonePrefix + "/Key").getValue(null);
+ try {
+ blacklistSone(getSone(blacklistedSoneId).setName(blacklistedSoneName).setRequestUri(new FreenetURI(blacklistedSoneKey)));
+ } catch (MalformedURLException mue1) {
+ logger.log(Level.WARNING, "Could not create blacklisted Sone from requestUri (“" + blacklistedSoneKey + "”)!", mue1);
+ }
+ }
+
/* load all remote Sones. */
for (Sone remoteSone : getRemoteSones()) {
loadSone(remoteSone);
}
configuration.getStringValue("KnownSone." + knownSonesCounter + "/ID").setValue(null);
+ /* write all blacklisted Sones. */
+ int blacklistedSonesCounter = 0;
+ for (Sone blacklistedSone : getBlacklistedSones()) {
+ String blacklistedSonePrefix = "BlacklistedSone." + blacklistedSonesCounter++;
+ configuration.getStringValue(blacklistedSonePrefix + "/ID").setValue(blacklistedSone.getId());
+ configuration.getStringValue(blacklistedSonePrefix + "/Name").setValue(blacklistedSone.getName());
+ configuration.getStringValue(blacklistedSonePrefix + "/Key").setValue(blacklistedSone.getRequestUri().toString());
+ /* TODO - store all known stuff? */
+ }
+ configuration.getStringValue("BlacklistedSone." + blacklistedSonesCounter + "/ID").setValue(null);
+
} catch (ConfigurationException ce1) {
logger.log(Level.WARNING, "Could not store configuration!", ce1);
}
} else if (member.equals("blocked")) {
Sone currentSone = (Sone) dataProvider.getData("currentSone");
return (currentSone != null) && currentSone.isSoneBlocked(sone.getId());
+ } else if (member.equals("blacklisted")) {
+ return core.isBlacklistedSone(sone);
} else if (member.equals("modified")) {
return sone.getModificationCounter() > 0;
} else if (member.equals("status")) {
--- /dev/null
+/*
+ * Sone - BlacklistPage.java - Copyright © 2010 David Roden
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.web;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.template.SoneAccessor;
+import net.pterodactylus.util.template.Template;
+
+/**
+ * This page lets the user manage Sone’s global blacklist.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class BlacklistPage extends SoneTemplatePage {
+
+ /**
+ * Creates a new blacklist management page.
+ *
+ * @param template
+ * The template to render
+ * @param webInterface
+ * The Sone web interface
+ */
+ public BlacklistPage(Template template, WebInterface webInterface) {
+ super("blacklist.html", template, "Page.Blacklist.Title", webInterface);
+ }
+
+ //
+ // TEMPLATEPAGE METHODS
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void processTemplate(Request request, Template template) throws RedirectException {
+ super.processTemplate(request, template);
+ List<Sone> blacklistedSones = new ArrayList<Sone>(webInterface.core().getBlacklistedSones());
+ Collections.sort(blacklistedSones, new Comparator<Sone>() {
+
+ @Override
+ public int compare(Sone leftSone, Sone rightSone) {
+ return SoneAccessor.getNiceName(leftSone).compareTo(SoneAccessor.getNiceName(rightSone));
+ }
+
+ });
+ template.set("blacklistedSones", blacklistedSones);
+ }
+
+}
--- /dev/null
+/*
+ * Sone - BlacklistSonePage.java - Copyright © 2010 David Roden
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.web;
+
+import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.web.page.Page.Request.Method;
+import net.pterodactylus.util.template.Template;
+
+/**
+ * This page lets the user blacklist a {@link Sone}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class BlacklistSonePage extends SoneTemplatePage {
+
+ /**
+ * Creates a new “blacklist Sone” page.
+ *
+ * @param template
+ * The template to render
+ * @param webInterface
+ * The Sone web interface
+ */
+ public BlacklistSonePage(Template template, WebInterface webInterface) {
+ super("blacklistSone.html", template, "Page.BlacklistSone.Title", webInterface);
+ }
+
+ //
+ // TEMPLATEPAGE METHODS
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void processTemplate(Request request, Template template) throws RedirectException {
+ super.processTemplate(request, template);
+ if (request.getMethod() == Method.POST) {
+ String soneId = request.getHttpRequest().getPartAsStringFailsafe("sone", 36);
+ String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 64);
+ Sone sone = webInterface.core().getSone(soneId);
+ webInterface.core().blacklistSone(sone);
+ throw new RedirectException(returnPage);
+ }
+ }
+
+ //
+ // SONETEMPLATEPAGE METHODS
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean requiresLogin() {
+ return false;
+ }
+
+}
--- /dev/null
+/*
+ * Sone - UnblacklistSonePage.java - Copyright © 2010 David Roden
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.web;
+
+import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.web.page.Page.Request.Method;
+import net.pterodactylus.util.template.Template;
+
+/**
+ * This page lets the user unblacklist a {@link Sone}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class UnblacklistSonePage extends SoneTemplatePage {
+
+ /**
+ * Creates a new “unblacklist Sone” page.
+ *
+ * @param template
+ * The template to render
+ * @param webInterface
+ * The Sone web interface
+ */
+ public UnblacklistSonePage(Template template, WebInterface webInterface) {
+ super("unblacklistSone.html", template, "Page.UnblacklistSone.Title", webInterface);
+ }
+
+ //
+ // TEMPLATEPAGE METHODS
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void processTemplate(Request request, Template template) throws RedirectException {
+ super.processTemplate(request, template);
+ if (request.getMethod() == Method.POST) {
+ String soneId = request.getHttpRequest().getPartAsStringFailsafe("sone", 36);
+ String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 64);
+ Sone sone = webInterface.core().getSone(soneId);
+ webInterface.core().unblacklistSone(sone);
+ throw new RedirectException(returnPage);
+ }
+ }
+
+ //
+ // SONETEMPLATEPAGE METHODS
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean requiresLogin() {
+ return false;
+ }
+
+}
Template noPermissionTemplate = templateFactory.createTemplate(createReader("/templates/noPermission.html"));
Template logoutTemplate = templateFactory.createTemplate(createReader("/templates/logout.html"));
Template optionsTemplate = templateFactory.createTemplate(createReader("/templates/options.html"));
+ Template blacklistTemplate = templateFactory.createTemplate(createReader("/templates/blacklist.html"));
+ Template blacklistSoneTemplate = templateFactory.createTemplate(createReader("/templates/blacklistSone.html"));
+ Template unblacklistSoneTemplate = templateFactory.createTemplate(createReader("/templates/unblacklistSone.html"));
Template aboutTemplate = templateFactory.createTemplate(createReader("/templates/about.html"));
PageToadletFactory pageToadletFactory = new PageToadletFactory(sonePlugin.pluginRespirator().getHLSimpleClient(), "/Sone/");
pageToadlets.add(pageToadletFactory.createPageToadlet(new LoginPage(loginTemplate, this), "Login"));
pageToadlets.add(pageToadletFactory.createPageToadlet(new LogoutPage(logoutTemplate, this), "Logout"));
pageToadlets.add(pageToadletFactory.createPageToadlet(new OptionsPage(optionsTemplate, this), "Options"));
+ pageToadlets.add(pageToadletFactory.createPageToadlet(new BlacklistPage(blacklistTemplate, this), "Blacklist"));
+ pageToadlets.add(pageToadletFactory.createPageToadlet(new BlacklistSonePage(blacklistSoneTemplate, this)));
+ pageToadlets.add(pageToadletFactory.createPageToadlet(new UnblacklistSonePage(unblacklistSoneTemplate, this)));
pageToadlets.add(pageToadletFactory.createPageToadlet(new SoneTemplatePage("about.html", aboutTemplate, "Page.About.Title", this), "About"));
pageToadlets.add(pageToadletFactory.createPageToadlet(new SoneTemplatePage("noPermission.html", noPermissionTemplate, "Page.NoPermission.Title", this)));
pageToadlets.add(pageToadletFactory.createPageToadlet(new StaticPage("css/", "/static/css/", "text/css")));
Navigation.Menu.Item.Logout.Tooltip=Logs you out of the current Sone
Navigation.Menu.Item.Options.Name=Options
Navigation.Menu.Item.Options.Tooltip=Options for the Sone plugin
+Navigation.Menu.Item.Blacklist.Name=Blacklist
+Navigation.Menu.Item.Blacklist.Tooltip=Manages the global blacklist
Navigation.Menu.Item.About.Name=About
Navigation.Menu.Item.About.Tooltip=Information about Sone
Page.Options.Option.ReallyClearOnNextRestart.Description=This option needs to be set to “yes” if you really, {strong}really{/strong} want to clear the plugin configuration on the next restart.
Page.Options.Button.Save=Save
+Page.Blacklist.Title=Blacklist - Sone
+Page.Blacklist.Page.Title=Blacklist
+Page.Blacklist.Text.Description=The Sone on the blacklist are prevented from being distributed with your next Sone updates, and there will be no updates fetched for these Sones.
+Page.Blacklist.Text.Empty=There are currently no Sones in the blacklist.
+
+Page.BlacklistSone.Title=Blacklist Sone - Sone
+
+Page.UnblacklistSone.Title=Unblacklist Sone - Sone
+
Page.Login.Title=Login - Sone
Page.Login.Page.Title=Login
Page.Login.Label.SelectSone=Select Sone:
View.Sone.Button.FollowSone=follow
View.Sone.Button.UnblockSone=unblock
View.Sone.Button.BlockSone=block
+View.Sone.Button.BlacklistSone=blacklist
+View.Sone.Button.UnblacklistSone=unblacklist
View.Sone.Status.Modified=This Sone was modified and waits to be inserted.
View.Sone.Status.Unknown=This Sone has not yet been retrieved.
View.Sone.Status.Idle=This Sone is idle, i.e. not being inserted or downloaded.
display: none;
}
-#sone .sone form.block button, #sone .sone form.unblock button, #sone .sone form.follow button, #sone .sone form.unfollow button {
+#sone .sone form.block button, #sone .sone form.unblock button, #sone .sone form.follow button, #sone .sone form.unfollow button, #sone .sone form.blacklist button, #sone .sone form.unblacklist button {
display: inline;
color: rgb(28, 131, 191);
background: none;
padding: 0px;
}
-#sone .sone form.block button:hover, #sone .sone form.unblock button:hover, #sone .sone form.follow button:hover, #sone .sone form.unfollow button:hover {
+#sone .sone form.block button:hover, #sone .sone form.unblock button:hover, #sone .sone form.follow button:hover, #sone .sone form.unfollow button:hover, #sone .sone form.blacklist button:hover, #sone .sone form.unblacklist button:hover {
display: inline;
color: rgb(255, 172, 0);
}
--- /dev/null
+<%include include/head.html>
+
+ <h1><%= Page.Blacklist.Page.Title|l10n|html></h1>
+
+ <p><%= Page.Blacklist.Text.Description|l10n|html></p>
+
+ <div id="blacklist">
+ <%getpage>
+ <%paginate list=blacklistedSones pagesize=25>
+ <%= page|store key=pageParameter>
+ <%include include/pagination.html>
+ <%foreach pagination.items sone>
+ <%include include/viewSone.html>
+ <%foreachelse>
+ <p><%= Page.Blacklist.Text.Empty|l10n|html></p>
+ <%/foreach>
+ <%include include/pagination.html>
+ </div>
+
+<%include include/tail.html>
--- /dev/null
+<%include include/head.html>
+
+<%include include/tail.html>
<div class="last-update"><%= View.Sone.Label.LastUpdate|l10n|html> <span class="time"><% sone.time|date format="MMM d, yyyy, HH:mm:ss"></span></div>
<div class="profile-link"><a href="viewSone.html?sone=<% sone.id|html>" title="<% sone.requestUri|html>"><% sone.niceName|html></a></div>
<div class="short-request-uri"><% sone.requestUri|substring start=4 length=43|html></div>
- <%ifnull ! currentSone>
- <%if ! sone.current>
- <form class="unfollow<%if ! sone.friend> hidden<%/if>" action="unfollowSone.html" method="post">
+ <div class="hidden"><% sone.blacklisted></div>
+ <%if ! sone.current>
+ <%if ! sone.blacklisted>
+ <form class="blacklist" action="blacklistSone.html" method="post">
<input type="hidden" name="formPassword" value="<% formPassword|html>" />
<input type="hidden" name="sone" value="<% sone.id|html>" />
<input type="hidden" name="returnPage" value="<% request.uri|html>" />
- <button type="submit"><%= View.Sone.Button.UnfollowSone|l10n|html></button>
+ <button type="submit"><%= View.Sone.Button.BlacklistSone|l10n|html></button>
</form>
- <form class="follow<%if sone.friend> hidden<%/if>" action="followSone.html" method="post">
+ <%ifnull ! currentSone>
+ <form class="unfollow<%if ! sone.friend> hidden<%/if>" action="unfollowSone.html" method="post">
+ <input type="hidden" name="formPassword" value="<% formPassword|html>" />
+ <input type="hidden" name="sone" value="<% sone.id|html>" />
+ <input type="hidden" name="returnPage" value="<% request.uri|html>" />
+ <button type="submit"><%= View.Sone.Button.UnfollowSone|l10n|html></button>
+ </form>
+ <form class="follow<%if sone.friend> hidden<%/if>" action="followSone.html" method="post">
+ <input type="hidden" name="formPassword" value="<% formPassword|html>" />
+ <input type="hidden" name="sone" value="<% sone.id|html>" />
+ <input type="hidden" name="returnPage" value="<% request.uri|html>" />
+ <button type="submit"><%= View.Sone.Button.FollowSone|l10n|html></button>
+ </form>
+ <form class="unblock<%if ! sone.blocked> hidden<%/if>" action="unblockSone.html" method="post">
+ <input type="hidden" name="formPassword" value="<% formPassword|html>" />
+ <input type="hidden" name="sone" value="<% sone.id|html>" />
+ <input type="hidden" name="returnPage" value="<% request.uri|html>" />
+ <button type="submit"><%= View.Sone.Button.UnblockSone|l10n|html></button>
+ </form>
+ <form class="block<%if sone.blocked> hidden<%/if>" action="blockSone.html" method="post">
+ <input type="hidden" name="formPassword" value="<% formPassword|html>" />
+ <input type="hidden" name="sone" value="<% sone.id|html>" />
+ <input type="hidden" name="returnPage" value="<% request.uri|html>" />
+ <button type="submit"><%= View.Sone.Button.BlockSone|l10n|html></button>
+ </form>
+ <%/if>
+ <%else>
+ <form class="unblacklist" action="unblacklistSone.html" method="post">
<input type="hidden" name="formPassword" value="<% formPassword|html>" />
<input type="hidden" name="sone" value="<% sone.id|html>" />
<input type="hidden" name="returnPage" value="<% request.uri|html>" />
- <button type="submit"><%= View.Sone.Button.FollowSone|l10n|html></button>
- </form>
- <form class="unblock<%if ! sone.blocked> hidden<%/if>" action="unblockSone.html" method="post">
- <input type="hidden" name="formPassword" value="<% formPassword|html>" />
- <input type="hidden" name="sone" value="<% sone.id|html>" />
- <input type="hidden" name="returnPage" value="<% request.uri|html>" />
- <button type="submit"><%= View.Sone.Button.UnblockSone|l10n|html></button>
- </form>
- <form class="block<%if sone.blocked> hidden<%/if>" action="blockSone.html" method="post">
- <input type="hidden" name="formPassword" value="<% formPassword|html>" />
- <input type="hidden" name="sone" value="<% sone.id|html>" />
- <input type="hidden" name="returnPage" value="<% request.uri|html>" />
- <button type="submit"><%= View.Sone.Button.BlockSone|l10n|html></button>
+ <button type="submit"><%= View.Sone.Button.UnblacklistSone|l10n|html></button>
</form>
<%/if>
<%/if>
--- /dev/null
+<%include include/head.html>
+
+<%include include/tail.html>