Changeset ce043943


Ignore:
Timestamp:
Mar 23, 2019 4:42:37 PM (14 months ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
64039ee
Parents:
fea5bd4
Message:

SusiDNS: Add import feature (ticket #2447)
Box overlap issue remains todo, see ticket #2419

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • apps/susidns/src/build.xml

    rfea5bd4 rce043943  
    9898            <replacefilter token="&lt;!-- precompiled servlets --&gt;" value="${jspc.web.fragment}" />
    9999        </replace>
     100        <!-- Add multipart config to servlets that need them -->
     101        <property name="__match1" value="&lt;servlet-class&gt;i2p.susi.dns.jsp." />
     102        <property name="__match2" value="_jsp&lt;/servlet-class&gt;" />
     103        <property name="__class1" value="${__match1}addressbook${__match2}" />
     104        <property name="__multipart" value="&#10;
     105       &lt;multipart-config&gt;&#10;
     106           &lt;max-file-size&gt;67108864&lt;/max-file-size&gt;&#10;
     107           &lt;max-request-size&gt;67108864&lt;/max-request-size&gt;&#10;
     108           &lt;file-size-threshold&gt;262144&lt;/file-size-threshold&gt;&#10;
     109       &lt;/multipart-config&gt;" />
     110        <replace file="WEB-INF/web-out.xml">
     111            <replacefilter token="${__class1}" value="${__class1}${__multipart}" />
     112        </replace>
    100113    </target>
    101114
  • apps/susidns/src/java/src/i2p/susi/dns/NamingServiceBean.java

    rfea5bd4 rce043943  
    2222package i2p.susi.dns;
    2323
     24import java.io.File;
     25import java.io.FileOutputStream;
    2426import java.io.IOException;
     27import java.io.InputStream;
     28import java.io.OutputStream;
    2529import java.io.Writer;
    2630import java.util.Arrays;
     
    3539
    3640import net.i2p.client.naming.NamingService;
     41import net.i2p.client.naming.SingleFileNamingService;
    3742import net.i2p.data.DataFormatException;
    3843import net.i2p.data.DataHelper;
    3944import net.i2p.data.Destination;
     45import net.i2p.servlet.RequestWrapper;
    4046
    4147/**
     
    357363               
    358364                if( message.length() > 0 )
    359                         message = "<p class=\"messages\">" + message + "</p>";
     365                        message = styleMessage(message);
    360366                return message;
    361367        }
     
    496502
    497503        /**
     504         *  @return messages about this action
     505         *  @since 0.9.40
     506         */
     507        public String importFile(RequestWrapper wrequest) throws IOException {
     508                String message = "";
     509                InputStream in = wrequest.getInputStream("file");
     510                OutputStream out = null;
     511                File tmp = null;
     512                SingleFileNamingService sfns = null;
     513                try {
     514                        // non-null but zero bytes if no file entered, don't know why
     515                        if (in == null || in.available() <= 0) {
     516                                return styleMessage(_t("You must enter a file"));
     517                        }
     518                        // copy to temp file
     519                        tmp = new File(_context.getTempDir(), "susidns-import-" + _context.random().nextLong() + ".txt");
     520                        out = new FileOutputStream(tmp);
     521                        DataHelper.copy(in, out);
     522                        in.close();
     523                        in = null;
     524                        out.close();
     525                        out = null;
     526                        // new SingleFileNamingService
     527                        sfns = new SingleFileNamingService(_context, tmp.getAbsolutePath());
     528                        // getEntries, copy over
     529                        Map<String, Destination> entries = sfns.getEntries();
     530                        int count = entries.size();
     531                        if (count <= 0) {
     532                                return styleMessage(_t("No entries found in file"));
     533                        } else {
     534                                NamingService service = getNamingService();
     535                                int added = 0, dup = 0;
     536                                Properties nsOptions = new Properties();
     537                                nsOptions.setProperty("list", getFileName());
     538                                String now = Long.toString(_context.clock().now());
     539                                nsOptions.setProperty("m", now);
     540                                String filename = wrequest.getFilename("file");
     541                                if (filename != null)
     542                                        nsOptions.setProperty("s", _t("Imported from file {0}", filename));
     543                                else
     544                                        nsOptions.setProperty("s", _t("Imported from file"));
     545                                for (Map.Entry<String, Destination> e : entries.entrySet()) {
     546                                        String host = e.getKey();
     547                                        Destination dest = e.getValue();
     548                                        boolean ok = service.putIfAbsent(host, dest, nsOptions);
     549                                        if (ok)
     550                                                added++;
     551                                        else
     552                                                dup++;
     553                                }
     554                                StringBuilder buf = new StringBuilder(128);
     555                                if (added > 0)
     556                                        buf.append(styleMessage(ngettext("Loaded {0} entry from file",
     557                                                                         "Loaded {0} entries from file",
     558                                                                         added)));
     559                                if (dup > 0)
     560                                        buf.append(styleMessage(ngettext("Skipped {0} duplicate entry from file",
     561                                                                         "Skipped {0} duplicate entries from file",
     562                                                                         dup)));
     563                                return buf.toString();
     564                        }
     565                } catch (IOException ioe) {
     566                        return styleMessage(_t("Import from file failed") + " - " + ioe);
     567                } finally {
     568                        if (in != null)
     569                                try { in.close(); } catch (IOException ioe) {}
     570                        if (out != null)
     571                                try { out.close(); } catch (IOException ioe) {}
     572                        // shutdown SFNS
     573                        if (sfns != null)
     574                            sfns.shutdown();
     575                        if (tmp != null)
     576                            tmp.delete();
     577                }
     578        }
     579
     580        /**
     581         *  @since 0.9.40
     582         */
     583        private static String styleMessage(String message) {
     584                return "<p class=\"messages\">" + message + "</p>";
     585        }
     586       
     587        /**
    498588         *  @since 0.9.34
    499589         */
  • apps/susidns/src/jsp/addressbook.jsp

    rfea5bd4 rce043943  
    3535    response.setHeader("Accept-Ranges", "none");
    3636
    37 %>
    38 <%@page pageEncoding="UTF-8"%>
    39 <%@ page contentType="text/html"%>
    40 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
     37%><%@page pageEncoding="UTF-8" contentType="text/html" import="net.i2p.servlet.RequestWrapper"
     38%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    4139<jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application" />
    4240<jsp:useBean id="book" class="i2p.susi.dns.NamingServiceBean" scope="session" />
    4341<jsp:useBean id="intl" class="i2p.susi.dns.Messages" scope="application" />
     42<%
     43   String importMessages = null;
     44   if (intl._t("Import").equals(request.getParameter("action"))) {
     45       RequestWrapper wrequest = new RequestWrapper(request);
     46       importMessages = book.importFile(wrequest);
     47   }
     48%>
    4449<jsp:setProperty name="book" property="*" />
    4550<jsp:setProperty name="book" property="resetDeletionMarks" value="1"/>
     
    7681</div>
    7782
    78 <div id="messages">${book.messages}</div>
     83<div id="messages">${book.messages}<%
     84   if (importMessages != null) {
     85       %><%=importMessages%><%
     86   }
     87%></div>
    7988
    8089${book.loadBookMessages}
     
    255264</form>
    256265
     266<% if (!book.getBook().equals("published")) { %>
     267<form method="POST" action="addressbook" enctype="multipart/form-data" accept-charset="UTF-8">
     268<input type="hidden" name="book" value="${book.book}">
     269<input type="hidden" name="serial" value="<%=susiNonce%>">
     270<input type="hidden" name="begin" value="0">
     271<input type="hidden" name="end" value="49">
     272<div id="import">
     273<h3><%=intl._t("Import from hosts.txt file")%></h3>
     274<table>
     275<tr>
     276<td><b><%=intl._t("File")%></b></td>
     277<td><input name="file" type="file" accept=".txt" value="" /></td>
     278</tr>
     279</table>
     280<p class="buttons">
     281<input class="cancel" type="reset" value="<%=intl._t("Cancel")%>" >
     282<input class="download" type="submit" name="action" value="<%=intl._t("Import")%>" >
     283</p>
     284</div>
     285</form>
     286<% } %>
     287
    257288<div id="footer">
    258289<hr>
  • core/java/src/net/i2p/client/naming/SingleFileNamingService.java

    rfea5bd4 rce043943  
    347347
    348348    /**
    349      * @param options As follows:
     349     * @param options null OK, or as follows:
    350350     *                Key "search": return only those matching substring
    351351     *                Key "startsWith": return only those starting with
     
    414414     *  Overridden since we store base64 natively.
    415415     *
    416      *  @param options As follows:
     416     *  @param options null OK, or as follows:
    417417     *                 Key "search": return only those matching substring
    418418     *                 Key "startsWith": return only those starting with
  • installer/resources/themes/susidns/dark/susidns.css

    rfea5bd4 rce043943  
    752752}
    753753
    754 div#add {
     754div#add, div#import {
    755755     border: 1px solid #2a5f29;
    756756     padding: 0 0 10px;
     
    759759}
    760760
    761 #add h3 {
     761#add h3, #import h3 {
    762762     margin-top: -6px;
    763763     margin-left: -1px;
     
    767767}
    768768
    769 #add table {
     769#add table, #import table {
    770770     width: 100%;
    771771     width: calc(100% - 1px);
     
    773773}
    774774
    775 #add td:first-child {
     775#add td:first-child,
     776#import table td:first-child {
    776777     text-align: right;
    777778}
    778779
    779 #add td:last-child {
     780#add td:last-child,
     781#import td:last-child {
    780782     width: 94%;
    781783}
    782784
    783 #add p.buttons {
     785#add p.buttons, #import p.buttons {
    784786     margin-top: 5px;
    785787     border-top: 1px solid #2a5f29;
  • installer/resources/themes/susidns/light/susidns.css

    rfea5bd4 rce043943  
    271271}
    272272
    273 div#add {
     273div#add, div#import {
    274274     border: 1px solid #7778bf;
    275275     margin-top: -1px;
     
    278278}
    279279
    280 .iframed #add {
     280.iframed #add, .iframed #import {
    281281     margin-top: 10px;
    282282}
    283283
    284 #add h3 {
     284#add h3, #import h3 {
    285285     border-bottom: 1px solid #7778bf;
    286286     margin: 0 -15px;
     
    288288}
    289289
    290 #add table {
     290#add table, #import table {
    291291     width: 100%;
    292292     margin: 5px 0;
    293293}
    294294
    295 #add table td:first-child {
     295#add table td:first-child,
     296#import table td:first-child {
    296297     width: 50px;
    297298     white-space: nowrap;
     
    299300}
    300301
    301 #add td {
     302#add td, #import td {
    302303     padding: 3px;
    303304}
    304305
    305 div#add p.buttons {
     306div#add p.buttons, div#import p.buttons {
    306307     border: 1px solid #7778bf;
    307308     margin: 0 -16px -1px;
     
    328329}
    329330
    330 div.help h3, #add h3 {
     331div.help h3, #add h3, #import h3 {
    331332     border: 1px solid #7778bf;
    332333     padding: 5px 10px;
Note: See TracChangeset for help on using the changeset viewer.