forked from I2P_Developers/i2p.i2p
- Add details page in susidns
- Add source in Daemon - Honor list property in BFNS.lookup()
This commit is contained in:
@@ -115,6 +115,7 @@ public class Daemon {
|
|||||||
// If it is a text file, we do things differently, to avoid O(n**2) behavior
|
// If it is a text file, we do things differently, to avoid O(n**2) behavior
|
||||||
// when scanning large subscription results (i.e. those that return the whole file, not just the new entries) -
|
// when scanning large subscription results (i.e. those that return the whole file, not just the new entries) -
|
||||||
// we load all the known hostnames into a Set one time.
|
// we load all the known hostnames into a Set one time.
|
||||||
|
// This also has the advantage of not flushing the NamingService's LRU cache.
|
||||||
String nsClass = router.getClass().getSimpleName();
|
String nsClass = router.getClass().getSimpleName();
|
||||||
boolean isTextFile = nsClass.equals("HostsTxtNamingService") || nsClass.equals("SingleFileNamingService");
|
boolean isTextFile = nsClass.equals("HostsTxtNamingService") || nsClass.equals("SingleFileNamingService");
|
||||||
Set<String> knownNames = null;
|
Set<String> knownNames = null;
|
||||||
@@ -152,7 +153,9 @@ public class Daemon {
|
|||||||
if (!isKnown) {
|
if (!isKnown) {
|
||||||
if (AddressBook.isValidKey(key)) {
|
if (AddressBook.isValidKey(key)) {
|
||||||
Destination dest = new Destination(entry.getValue());
|
Destination dest = new Destination(entry.getValue());
|
||||||
boolean success = router.put(key, dest);
|
Properties props = new Properties();
|
||||||
|
props.setProperty("s", sub.getLocation());
|
||||||
|
boolean success = router.put(key, dest, props);
|
||||||
if (log != null) {
|
if (log != null) {
|
||||||
if (success)
|
if (success)
|
||||||
log.append("New address " + key +
|
log.append("New address " + key +
|
||||||
|
@@ -24,18 +24,18 @@
|
|||||||
|
|
||||||
package i2p.susi.dns;
|
package i2p.susi.dns;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.data.Base32;
|
import net.i2p.data.Base32;
|
||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
|
import net.i2p.data.Certificate;
|
||||||
|
|
||||||
public class AddressBean
|
public class AddressBean
|
||||||
{
|
{
|
||||||
private String name, destination;
|
private final String name, destination;
|
||||||
|
private Properties props;
|
||||||
public AddressBean()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddressBean(String name, String destination)
|
public AddressBean(String name, String destination)
|
||||||
{
|
{
|
||||||
@@ -48,21 +48,11 @@ public class AddressBean
|
|||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDestination(String destination)
|
|
||||||
{
|
|
||||||
this.destination = destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName()
|
public String getName()
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name)
|
|
||||||
{
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @since 0.8.6 */
|
/** @since 0.8.6 */
|
||||||
public String getB32()
|
public String getB32()
|
||||||
{
|
{
|
||||||
@@ -72,4 +62,88 @@ public class AddressBean
|
|||||||
byte[] hash = I2PAppContext.getGlobalContext().sha().calculateHash(dest).getData();
|
byte[] hash = I2PAppContext.getGlobalContext().sha().calculateHash(dest).getData();
|
||||||
return Base32.encode(hash) + ".b32.i2p";
|
return Base32.encode(hash) + ".b32.i2p";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.8.6 */
|
||||||
|
public void setProperties(Properties p) {
|
||||||
|
props = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.8.6 */
|
||||||
|
public String getSource() {
|
||||||
|
String rv = getProp("s");
|
||||||
|
if (rv.startsWith("http://"))
|
||||||
|
rv = "<a href=\"" + rv + "\">" + rv + "</a>";
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.8.6 */
|
||||||
|
public String getAdded() {
|
||||||
|
return getDate("a");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.8.6 */
|
||||||
|
public String getModded() {
|
||||||
|
return getDate("m");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @since 0.8.6 */
|
||||||
|
public String getNotes() {
|
||||||
|
return getProp("notes");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do this the easy way
|
||||||
|
* @since 0.8.6
|
||||||
|
*/
|
||||||
|
public String getCert() {
|
||||||
|
// (4 / 3) * (pubkey length + signing key length)
|
||||||
|
String cert = destination.substring(512);
|
||||||
|
if (cert.equals("AAAA"))
|
||||||
|
return _("None");
|
||||||
|
byte[] enc = Base64.decode(cert);
|
||||||
|
if (enc == null)
|
||||||
|
// shouldn't happen
|
||||||
|
return "invalid";
|
||||||
|
int type = enc[0] & 0xff;
|
||||||
|
switch (type) {
|
||||||
|
case Certificate.CERTIFICATE_TYPE_HASHCASH:
|
||||||
|
return _("Hashcash");
|
||||||
|
case Certificate.CERTIFICATE_TYPE_HIDDEN:
|
||||||
|
return _("Hidden");
|
||||||
|
case Certificate.CERTIFICATE_TYPE_SIGNED:
|
||||||
|
return _("Signed");
|
||||||
|
default:
|
||||||
|
return _("Type {0}", type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.8.6 */
|
||||||
|
private String getProp(String p) {
|
||||||
|
if (props == null)
|
||||||
|
return "";
|
||||||
|
String rv = props.getProperty(p);
|
||||||
|
return rv != null ? rv : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.8.6 */
|
||||||
|
private String getDate(String key) {
|
||||||
|
String d = getProp(key);
|
||||||
|
if (d.length() > 0) {
|
||||||
|
try {
|
||||||
|
d = FormatDate.format(Long.parseLong(d));
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** translate */
|
||||||
|
private static String _(String s) {
|
||||||
|
return Messages.getString(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** translate */
|
||||||
|
private static String _(String s, Object o) {
|
||||||
|
return Messages.getString(s, o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
30
apps/susidns/src/java/src/i2p/susi/dns/FormatDate.java
Normal file
30
apps/susidns/src/java/src/i2p/susi/dns/FormatDate.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package i2p.susi.dns;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a date in local time zone
|
||||||
|
* @since 0.8.6
|
||||||
|
*/
|
||||||
|
public abstract class FormatDate
|
||||||
|
{
|
||||||
|
private static final DateFormat _dateFormat;
|
||||||
|
|
||||||
|
static {
|
||||||
|
DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
|
||||||
|
// the router sets the JVM time zone to UTC but saves the original here so we can get it
|
||||||
|
String systemTimeZone = I2PAppContext.getGlobalContext().getProperty("i2p.systemTimeZone");
|
||||||
|
if (systemTimeZone != null)
|
||||||
|
fmt.setTimeZone(TimeZone.getTimeZone(systemTimeZone));
|
||||||
|
_dateFormat = fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String format(long date)
|
||||||
|
{
|
||||||
|
return _dateFormat.format(new Date(date));
|
||||||
|
}
|
||||||
|
}
|
@@ -45,6 +45,7 @@ import net.i2p.data.Destination;
|
|||||||
public class NamingServiceBean extends AddressbookBean
|
public class NamingServiceBean extends AddressbookBean
|
||||||
{
|
{
|
||||||
private static final String DEFAULT_NS = "BlockfileNamingService";
|
private static final String DEFAULT_NS = "BlockfileNamingService";
|
||||||
|
private String detail;
|
||||||
|
|
||||||
private boolean isDirect() {
|
private boolean isDirect() {
|
||||||
return getBook().equals("published");
|
return getBook().equals("published");
|
||||||
@@ -280,4 +281,22 @@ public class NamingServiceBean extends AddressbookBean
|
|||||||
message = "<p class=\"messages\">" + message + "</p>";
|
message = "<p class=\"messages\">" + message + "</p>";
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setH(String h) {
|
||||||
|
this.detail = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddressBean getLookup() {
|
||||||
|
if (this.detail == null)
|
||||||
|
return null;
|
||||||
|
Properties nsOptions = new Properties();
|
||||||
|
Properties outProps = new Properties();
|
||||||
|
nsOptions.setProperty("list", getFileName());
|
||||||
|
Destination dest = getNamingService().lookup(this.detail, nsOptions, outProps);
|
||||||
|
if (dest == null)
|
||||||
|
return null;
|
||||||
|
AddressBean rv = new AddressBean(this.detail, dest.toBase64());
|
||||||
|
rv.setProperties(outProps);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -153,7 +153,7 @@ ${book.loadBookMessages}
|
|||||||
<td class="names"><a href="http://${addr.name}/">${addr.name}</a>
|
<td class="names"><a href="http://${addr.name}/">${addr.name}</a>
|
||||||
</td><td class="names">
|
</td><td class="names">
|
||||||
<span class="addrhlpr">(<a href="http://${addr.b32}/">b32</a>)</span>
|
<span class="addrhlpr">(<a href="http://${addr.b32}/">b32</a>)</span>
|
||||||
<span class="addrhlpr">(<a href="http://${addr.name}/?i2paddresshelper=${addr.destination}"><%=intl._("helper")%></a>)</span>
|
<span class="addrhlpr">(<a href="details.jsp?h=${addr.name}"><%=intl._("details")%></a>)</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="destinations"><textarea rows="1" style="height: 3em;" cols="40" wrap="off" readonly="readonly" name="dest_${addr.name}" >${addr.destination}</textarea></td>
|
<td class="destinations"><textarea rows="1" style="height: 3em;" cols="40" wrap="off" readonly="readonly" name="dest_${addr.name}" >${addr.destination}</textarea></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
135
apps/susidns/src/jsp/details.jsp
Normal file
135
apps/susidns/src/jsp/details.jsp
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
<%
|
||||||
|
/*
|
||||||
|
* Created on Sep 02, 2005
|
||||||
|
*
|
||||||
|
* This file is part of susidns project, see http://susi.i2p/
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 <susi23@mail.i2p>
|
||||||
|
*
|
||||||
|
* 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 2 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* $Revision: 1.3 $
|
||||||
|
*/
|
||||||
|
|
||||||
|
// http://www.crazysquirrel.com/computing/general/form-encoding.jspx
|
||||||
|
if (request.getCharacterEncoding() == null)
|
||||||
|
request.setCharacterEncoding("UTF-8");
|
||||||
|
|
||||||
|
%>
|
||||||
|
<%@page pageEncoding="UTF-8"%>
|
||||||
|
<%@ page contentType="text/html"%>
|
||||||
|
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||||
|
<jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application" />
|
||||||
|
<jsp:useBean id="book" class="i2p.susi.dns.NamingServiceBean" scope="session" />
|
||||||
|
<jsp:useBean id="intl" class="i2p.susi.dns.Messages" scope="application" />
|
||||||
|
<jsp:setProperty name="book" property="*" />
|
||||||
|
<jsp:setProperty name="book" property="resetDeletionMarks" value="1"/>
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>${book.book} <%=intl._("addressbook")%> - susidns</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="css.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page">
|
||||||
|
<div id="logo">
|
||||||
|
<img src="images/logo.png" alt="susidns logo" border="0"/>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div id="navi">
|
||||||
|
<p>
|
||||||
|
<%=intl._("addressbooks")%>
|
||||||
|
<a href="addressbook.jsp?book=private&filter=none&begin=0&end=99"><%=intl._("private")%></a> |
|
||||||
|
<a href="addressbook.jsp?book=master&filter=none&begin=0&end=99"><%=intl._("master")%></a> |
|
||||||
|
<a href="addressbook.jsp?book=router&filter=none&begin=0&end=99"><%=intl._("router")%></a> |
|
||||||
|
<a href="addressbook.jsp?book=published&filter=none&begin=0&end=99"><%=intl._("published")%></a> *
|
||||||
|
<a href="subscriptions.jsp"><%=intl._("subscriptions")%></a> *
|
||||||
|
<a href="config.jsp"><%=intl._("configuration")%></a> *
|
||||||
|
<a href="index.jsp"><%=intl._("overview")%></a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div id="headline">
|
||||||
|
<h3><%=intl._(book.getBook())%> <%=intl._("addressbook")%>: ${book.fileName}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="book">
|
||||||
|
<%
|
||||||
|
String detail = request.getParameter("h");
|
||||||
|
if (detail == null) {
|
||||||
|
%><p>No host specified</p><%
|
||||||
|
} else {
|
||||||
|
i2p.susi.dns.AddressBean addr = book.getLookup();
|
||||||
|
if (addr == null) {
|
||||||
|
%><p>Not found: <%=detail%></p><%
|
||||||
|
} else {
|
||||||
|
String b32 = addr.getB32();
|
||||||
|
%>
|
||||||
|
<jsp:setProperty name="book" property="trClass" value="0" />
|
||||||
|
<table class="book" cellspacing="0" cellpadding="5">
|
||||||
|
<tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Host Name")%></td>
|
||||||
|
<td><a href="http://<%=addr.getName()%>/"><%=addr.getName()%></a></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Base 32 Address")%></td>
|
||||||
|
<td><a href="http://<%=b32%>/"><%=b32%></a></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Address Helper")%></td>
|
||||||
|
<td><a href="http://<%=addr.getName()%>/?i2paddresshelper=<%=addr.getDestination()%>"><%=intl._("link")%></a></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Public Key")%></td>
|
||||||
|
<td><%=intl._("ElGamal 2048 bit")%></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Signing Key")%></td>
|
||||||
|
<td><%=intl._("DSA 1024 bit")%></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Certificate")%></td>
|
||||||
|
<td><%=addr.getCert()%></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Added Date")%></td>
|
||||||
|
<td><%=addr.getAdded()%></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Source")%></td>
|
||||||
|
<td><%=addr.getSource()%></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Last Modified")%></td>
|
||||||
|
<td><%=addr.getModded()%></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Notes")%></td>
|
||||||
|
<td><%=addr.getNotes()%></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Destination")%></td>
|
||||||
|
<td class="destinations"><textarea rows="1" style="height: 3em;" cols="70" wrap="off" readonly="readonly" ><%=addr.getDestination()%></textarea></td>
|
||||||
|
</tr></table>
|
||||||
|
</div>
|
||||||
|
<div id="buttons">
|
||||||
|
<form method="POST" action="details.jsp">
|
||||||
|
<input type="hidden" name="serial" value="${book.serial}">
|
||||||
|
<input type="hidden" name="h" value="<%=detail%>">
|
||||||
|
<input type="submit" name="action" value="<%=intl._("Delete")%>" >
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
<hr>
|
||||||
|
<div id="footer">
|
||||||
|
<p class="footer">susidns v${version.version} © <a href="${version.url}">susi</a> 2005</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@@ -347,17 +347,31 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
|
|
||||||
////////// Start NamingService API
|
////////// Start NamingService API
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param options If non-null and contains the key "list", lookup in
|
||||||
|
* that list only, otherwise all lists
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) {
|
public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) {
|
||||||
Destination d = super.lookup(hostname, null, null);
|
String listname = null;
|
||||||
|
if (lookupOptions != null)
|
||||||
|
listname = lookupOptions.getProperty("list");
|
||||||
|
|
||||||
|
Destination d = null;
|
||||||
|
// only use cache if we aren't retreiving options or specifying the list
|
||||||
|
if (listname == null && storedOptions == null) {
|
||||||
|
d = super.lookup(hostname, null, null);
|
||||||
if (d != null)
|
if (d != null)
|
||||||
return d;
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
String key = hostname.toLowerCase();
|
String key = hostname.toLowerCase();
|
||||||
synchronized(_bf) {
|
synchronized(_bf) {
|
||||||
if (_isClosed)
|
if (_isClosed)
|
||||||
return null;
|
return null;
|
||||||
for (String list : _lists) {
|
for (String list : _lists) {
|
||||||
|
if (listname != null && !list.equals(listname))
|
||||||
|
continue;
|
||||||
try {
|
try {
|
||||||
DestEntry de = getEntry(list, key);
|
DestEntry de = getEntry(list, key);
|
||||||
if (de != null) {
|
if (de != null) {
|
||||||
|
Reference in New Issue
Block a user