Changes in / [f43b0be:2b81cee]


Ignore:
Files:
38 added
18 deleted
163 edited

Legend:

Unmodified
Added
Removed
  • apps/addressbook/build.xml

    rf43b0be r2b81cee  
    5757                                <attribute name="Main-Class" value="addressbook.Daemon"/>
    5858                                <attribute name="Implementation-Version" value="${full.version}" />
     59                                <attribute name="Built-By" value="${build.built-by}" />
    5960                                <attribute name="Build-Date" value="${build.timestamp}" />
    6061                                <attribute name="Base-Revision" value="${workspace.version}" />
     
    7677                        <manifest>
    7778                                <attribute name="Implementation-Version" value="${full.version}" />
     79                                <attribute name="Built-By" value="${build.built-by}" />
    7880                                <attribute name="Build-Date" value="${build.timestamp}" />
    7981                                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/i2psnark/java/build.xml

    rf43b0be r2b81cee  
    6363                <attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
    6464                <attribute name="Implementation-Version" value="${full.version}" />
     65                <attribute name="Built-By" value="${build.built-by}" />
    6566                <attribute name="Build-Date" value="${build.timestamp}" />
    6667                <attribute name="Base-Revision" value="${workspace.version}" />
     
    9798        <!-- set if unset -->
    9899        <property name="workspace.changes.tr" value="" />
    99         <war destfile="../i2psnark.war" webxml="../web.xml" basedir="../" includes="_icons/*" >
     100        <copy todir="build/icons/.icons" >
     101            <fileset dir="../icons/" />
     102        </copy>
     103        <war destfile="../i2psnark.war" webxml="../web.xml" >
    100104          <!-- include only the web stuff, as of 0.7.12 the router will add i2psnark.jar to the classpath for the war -->
    101105          <classes dir="./build/obj" includes="**/web/*.class" />
     106            <fileset dir="build/icons/" />
    102107            <manifest>
    103108                <attribute name="Implementation-Version" value="${full.version}" />
     109                <attribute name="Built-By" value="${build.built-by}" />
    104110                <attribute name="Build-Date" value="${build.timestamp}" />
    105111                <attribute name="Base-Revision" value="${workspace.version}" />
     
    111117    <target name="warUpToDate">
    112118        <uptodate property="war.uptodate" targetfile="../i2psnark.war" >
    113             <srcfiles dir= "." includes="build/obj/org/klomp/snark/web/*.class ../_icons/* ../web.xml" />
     119            <srcfiles dir= "." includes="build/obj/org/klomp/snark/web/*.class ../icons/* ../web.xml" />
    114120        </uptodate>
    115121    </target>
  • apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java

    rf43b0be r2b81cee  
    4040  /**
    4141   *  @param metasize -1 if unknown
     42   *  @param pexAndMetadata advertise these capabilities
    4243   *  @return bencoded outgoing handshake message
    4344   */
    44     public static byte[] getHandshake(int metasize) {
     45    public static byte[] getHandshake(int metasize, boolean pexAndMetadata) {
    4546        Map<String, Object> handshake = new HashMap();
    4647        Map<String, Integer> m = new HashMap();
    47         m.put(TYPE_METADATA, Integer.valueOf(ID_METADATA));
    48         m.put(TYPE_PEX, Integer.valueOf(ID_PEX));
    49         if (metasize >= 0)
    50             handshake.put("metadata_size", Integer.valueOf(metasize));
     48        if (pexAndMetadata) {
     49            m.put(TYPE_METADATA, Integer.valueOf(ID_METADATA));
     50            m.put(TYPE_PEX, Integer.valueOf(ID_PEX));
     51            if (metasize >= 0)
     52                handshake.put("metadata_size", Integer.valueOf(metasize));
     53        }
     54        // include the map even if empty so the far-end doesn't NPE
    5155        handshake.put("m", m);
    5256        handshake.put("p", Integer.valueOf(6881));
  • apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java

    rf43b0be r2b81cee  
    220220            //if (opts.getProperty("i2p.streaming.readTimeout") == null)
    221221            //    opts.setProperty("i2p.streaming.readTimeout", "120000");
     222            if (opts.getProperty("i2p.streaming.maxConnsPerMinute") == null)
     223                opts.setProperty("i2p.streaming.maxConnsPerMinute", "2");
     224            if (opts.getProperty("i2p.streaming.maxTotalConnsPerMinute") == null)
     225                opts.setProperty("i2p.streaming.maxTotalConnsPerMinute", "6");
    222226            _manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
    223227        }
  • apps/i2psnark/java/src/org/klomp/snark/MetaInfo.java

    rf43b0be r2b81cee  
    6262  private final byte[] piece_hashes;
    6363  private final long length;
     64  private final boolean privateTorrent;
    6465  private Map<String, BEValue> infoMap;
    6566
     
    7273   */
    7374  MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
    74            int piece_length, byte[] piece_hashes, long length)
     75           int piece_length, byte[] piece_hashes, long length, boolean privateTorrent)
    7576  {
    7677    this.announce = announce;
     
    8384    this.piece_hashes = piece_hashes;
    8485    this.length = length;
     86    this.privateTorrent = privateTorrent;
    8587
    8688    // TODO if we add a parameter for other keys
     
    160162    else
    161163        name_utf8 = null;
     164
     165    // BEP 27
     166    val = info.get("private");
     167    privateTorrent = val != null && val.getString().equals("1");
    162168
    163169    val = info.get("piece length");
     
    320326
    321327  /**
     328   * Is it a private torrent?
     329   * @since 0.9
     330   */
     331  public boolean isPrivate() {
     332    return privateTorrent;
     333  }
     334
     335  /**
    322336   * Returns a list of lists of file name hierarchies or null if it is
    323337   * a single name. It has the same size as the list returned by
     
    440454    return new MetaInfo(announce, name, name_utf8, files,
    441455                        lengths, piece_length,
    442                         piece_hashes, length);
     456                        piece_hashes, length, privateTorrent);
    443457  }
    444458
     
    476490    if (name_utf8 != null)
    477491        info.put("name.utf-8", name_utf8);
     492    // BEP 27
     493    if (privateTorrent)
     494        info.put("private", "1");
     495
    478496    info.put("piece length", Integer.valueOf(piece_length));
    479497    info.put("pieces", piece_hashes);
  • apps/i2psnark/java/src/org/klomp/snark/Peer.java

    rf43b0be r2b81cee  
    269269                _log.debug("Peer supports extensions, sending reply message");
    270270            int metasize = metainfo != null ? metainfo.getInfoBytes().length : -1;
    271             out.sendExtension(0, ExtensionHandler.getHandshake(metasize));
     271            boolean pexAndMetadata = metainfo == null || !metainfo.isPrivate();
     272            out.sendExtension(0, ExtensionHandler.getHandshake(metasize, pexAndMetadata));
    272273        }
    273274
  • apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java

    rf43b0be r2b81cee  
    11871187   */
    11881188  void sendPeers(Peer peer) {
     1189      if (metainfo != null && metainfo.isPrivate())
     1190          return;
    11891191      Map<String, BEValue> handshake = peer.getHandshakeMap();
    11901192      if (handshake == null)
  • apps/i2psnark/java/src/org/klomp/snark/PeerState.java

    rf43b0be r2b81cee  
    490490  void extensionMessage(int id, byte[] bs)
    491491  {
     492      if (metainfo != null && metainfo.isPrivate() &&
     493          (id == ExtensionHandler.ID_METADATA || id == ExtensionHandler.ID_PEX)) {
     494          // shouldn't get this since we didn't advertise it but they could send it anyway
     495          if (_log.shouldLog(Log.WARN))
     496              _log.warn("Private torrent, ignoring ext msg " + id);
     497          return;
     498      }
    492499      ExtensionHandler.handleMessage(peer, listener, id, bs);
    493500      // Peer coord will get metadata from MagnetState,
  • apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java

    rf43b0be r2b81cee  
    99import java.io.OutputStream;
    1010import java.util.ArrayList;
     11import java.util.Collections;
     12import java.util.Comparator;
    1113import java.util.HashMap;
    1214import java.util.HashSet;
     
    3638 */
    3739public class SnarkManager implements Snark.CompleteListener {
    38     private static SnarkManager _instance = new SnarkManager();
    39     public static SnarkManager instance() { return _instance; }
    4040   
    4141    /**
     
    5858    private Thread _monitor;
    5959    private volatile boolean _running;
     60    private final Map<String, String> _trackerMap;
    6061   
    6162    public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
     
    9091    public static final int DEFAULT_REFRESH_DELAY_SECS = 60;
    9192
     93    /**
     94     *  "name", "announceURL=websiteURL" pairs
     95     *  '=' in announceURL must be escaped as &#44;
     96     */
     97    private static final String DEFAULT_TRACKERS[] = {
     98//       "Postman", "http://YRgrgTLGnbTq2aZOZDJQ~o6Uk5k6TK-OZtx0St9pb0G-5EGYURZioxqYG8AQt~LgyyI~NCj6aYWpPO-150RcEvsfgXLR~CxkkZcVpgt6pns8SRc3Bi-QSAkXpJtloapRGcQfzTtwllokbdC-aMGpeDOjYLd8b5V9Im8wdCHYy7LRFxhEtGb~RL55DA8aYOgEXcTpr6RPPywbV~Qf3q5UK55el6Kex-6VCxreUnPEe4hmTAbqZNR7Fm0hpCiHKGoToRcygafpFqDw5frLXToYiqs9d4liyVB-BcOb0ihORbo0nS3CLmAwZGvdAP8BZ7cIYE3Z9IU9D1G8JCMxWarfKX1pix~6pIA-sp1gKlL1HhYhPMxwyxvuSqx34o3BqU7vdTYwWiLpGM~zU1~j9rHL7x60pVuYaXcFQDR4-QVy26b6Pt6BlAZoFmHhPcAuWfu-SFhjyZYsqzmEmHeYdAwa~HojSbofg0TMUgESRXMw6YThK1KXWeeJVeztGTz25sL8AAAA.i2p/announce.php=http://tracker.postman.i2p/"
     99//       , "eBook", "http://E71FRom6PZNEqTN2Lr8P-sr23b7HJVC32KoGnVQjaX6zJiXwhJy2HsXob36Qmj81TYFZdewFZa9mSJ533UZgGyQkXo2ahctg82JKYZfDe5uDxAn1E9YPjxZCWJaFJh0S~UwSs~9AZ7UcauSJIoNtpxrtbmRNVFLqnkEDdLZi26TeucfOmiFmIWnVblLniWv3tG1boE9Abd-6j3FmYVrRucYuepAILYt6katmVNOk6sXmno1Eynrp~~MBuFq0Ko6~jsc2E2CRVYXDhGHEMdt-j6JUz5D7S2RIVzDRqQyAZLKJ7OdQDmI31przzmne1vOqqqLC~1xUumZVIvF~yOeJUGNjJ1Vx0J8i2BQIusn1pQJ6UCB~ZtZZLQtEb8EPVCfpeRi2ri1M5CyOuxN0V5ekmPHrYIBNevuTCRC26NP7ZS5VDgx1~NaC3A-CzJAE6f1QXi0wMI9aywNG5KGzOPifcsih8eyGyytvgLtrZtV7ykzYpPCS-rDfITncpn5hliPUAAAA.i2p/pub/bt/announce.php=http://de-ebook-archiv.i2p/pub/bt/"
     100//       , "Gaytorrents", "http://uxPWHbK1OIj9HxquaXuhMiIvi21iK0~ZiG9d8G0840ZXIg0r6CbiV71xlsqmdnU6wm0T2LySriM0doW2gUigo-5BNkUquHwOjLROiETnB3ZR0Ml4IGa6QBPn1aAq2d9~g1r1nVjLE~pcFnXB~cNNS7kIhX1d6nLgYVZf0C2cZopEow2iWVUggGGnAA9mHjE86zLEnTvAyhbAMTqDQJhEuLa0ZYSORqzJDMkQt90MV4YMjX1ICY6RfUSFmxEqu0yWTrkHsTtRw48l~dz9wpIgc0a0T9C~eeWvmBFTqlJPtQZwntpNeH~jF7nlYzB58olgV2HHFYpVYD87DYNzTnmNWxCJ5AfDorm6AIUCV2qaE7tZtI1h6fbmGpGlPyW~Kw5GXrRfJwNvr6ajwAVi~bPVnrBwDZezHkfW4slOO8FACPR28EQvaTu9nwhAbqESxV2hCTq6vQSGjuxHeOuzBOEvRWkLKOHWTC09t2DbJ94FSqETmZopTB1ukEmaxRWbKSIaAAAA.i2p/announce.php=http://gaytorrents.i2p/"
     101//       , "NickyB", "http://9On6d3cZ27JjwYCtyJJbowe054d5tFnfMjv4PHsYs-EQn4Y4mk2zRixatvuAyXz2MmRfXG-NAUfhKr0KCxRNZbvHmlckYfT-WBzwwpiMAl0wDFY~Pl8cqXuhfikSG5WrqdPfDNNIBuuznS0dqaczf~OyVaoEOpvuP3qV6wKqbSSLpjOwwAaQPHjlRtNIW8-EtUZp-I0LT45HSoowp~6b7zYmpIyoATvIP~sT0g0MTrczWhbVTUZnEkZeLhOR0Duw1-IRXI2KHPbA24wLO9LdpKKUXed05RTz0QklW5ROgR6TYv7aXFufX8kC0-DaKvQ5JKG~h8lcoHvm1RCzNqVE-2aiZnO2xH08H-iCWoLNJE-Td2kT-Tsc~3QdQcnEUcL5BF-VT~QYRld2--9r0gfGl-yDrJZrlrihHGr5J7ImahelNn9PpkVp6eIyABRmJHf2iicrk3CtjeG1j9OgTSwaNmEpUpn4aN7Kx0zNLdH7z6uTgCGD9Kmh1MFYrsoNlTp4AAAA.i2p/bittorrent/announce.php=http://nickyb.i2p/bittorrent/"
     102//       , "Orion", "http://gKik1lMlRmuroXVGTZ~7v4Vez3L3ZSpddrGZBrxVriosCQf7iHu6CIk8t15BKsj~P0JJpxrofeuxtm7SCUAJEr0AIYSYw8XOmp35UfcRPQWyb1LsxUkMT4WqxAT3s1ClIICWlBu5An~q-Mm0VFlrYLIPBWlUFnfPR7jZ9uP5ZMSzTKSMYUWao3ejiykr~mtEmyls6g-ZbgKZawa9II4zjOy-hdxHgP-eXMDseFsrym4Gpxvy~3Fv9TuiSqhpgm~UeTo5YBfxn6~TahKtE~~sdCiSydqmKBhxAQ7uT9lda7xt96SS09OYMsIWxLeQUWhns-C~FjJPp1D~IuTrUpAFcVEGVL-BRMmdWbfOJEcWPZ~CBCQSO~VkuN1ebvIOr9JBerFMZSxZtFl8JwcrjCIBxeKPBmfh~xYh16BJm1BBBmN1fp2DKmZ2jBNkAmnUbjQOqWvUcehrykWk5lZbE7bjJMDFH48v3SXwRuDBiHZmSbsTY6zhGY~GkMQHNGxPMMSIAAAA.i2p/bt/announce.php=http://orion.i2p/bt/"
     103//       , "anonymity", "http://8EoJZIKrWgGuDrxA3nRJs1jsPfiGwmFWL91hBrf0HA7oKhEvAna4Ocx47VLUR9retVEYBAyWFK-eZTPcvhnz9XffBEiJQQ~kFSCqb1fV6IfPiV3HySqi9U5Caf6~hC46fRd~vYnxmaBLICT3N160cxBETqH3v2rdxdJpvYt8q4nMk9LUeVXq7zqCTFLLG5ig1uKgNzBGe58iNcsvTEYlnbYcE930ABmrzj8G1qQSgSwJ6wx3tUQNl1z~4wSOUMan~raZQD60lRK70GISjoX0-D0Po9WmPveN3ES3g72TIET3zc3WPdK2~lgmKGIs8GgNLES1cXTolvbPhdZK1gxddRMbJl6Y6IPFyQ9o4-6Rt3Lp-RMRWZ2TG7j2OMcNSiOmATUhKEFBDfv-~SODDyopGBmfeLw16F4NnYednvn4qP10dyMHcUASU6Zag4mfc2-WivrOqeWhD16fVAh8MoDpIIT~0r9XmwdaVFyLcjbXObabJczxCAW3fodQUnvuSkwzAAAA.i2p/anonymityTracker/announce.php=http://anonymityweb.i2p/anonymityTracker/"
     104//       , "The freak's tracker", "http://mHKva9x24E5Ygfey2llR1KyQHv5f8hhMpDMwJDg1U-hABpJ2NrQJd6azirdfaR0OKt4jDlmP2o4Qx0H598~AteyD~RJU~xcWYdcOE0dmJ2e9Y8-HY51ie0B1yD9FtIV72ZI-V3TzFDcs6nkdX9b81DwrAwwFzx0EfNvK1GLVWl59Ow85muoRTBA1q8SsZImxdyZ-TApTVlMYIQbdI4iQRwU9OmmtefrCe~ZOf4UBS9-KvNIqUL0XeBSqm0OU1jq-D10Ykg6KfqvuPnBYT1BYHFDQJXW5DdPKwcaQE4MtAdSGmj1epDoaEBUa9btQlFsM2l9Cyn1hzxqNWXELmx8dRlomQLlV4b586dRzW~fLlOPIGC13ntPXogvYvHVyEyptXkv890jC7DZNHyxZd5cyrKC36r9huKvhQAmNABT2Y~pOGwVrb~RpPwT0tBuPZ3lHYhBFYmD8y~AOhhNHKMLzea1rfwTvovBMByDdFps54gMN1mX4MbCGT4w70vIopS9yAAAA.i2p/bytemonsoon/announce.php"
     105//       , "mastertracker", "http://VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT8JD7i-C2xzYFa4jT5U2aqHzHI-Jre4HL3Ri5hFtZrLk2ax3ji7Qfb6qPnuYkuiF2E2UDmKUOppI8d9Ye7tjdhQVCy0izn55tBaB-U7UWdcvSK2i85sauyw3G0Gfads1Rvy5-CAe2paqyYATcDmGjpUNLoxbfv9KH1KmwRTNH6k1v4PyWYYnhbT39WfKMbBjSxVQRdi19cyJrULSWhjxaQfJHeWx5Z8Ev4bSPByBeQBFl2~4vqy0S5RypINsRSa3MZdbiAAyn5tr5slWR6QdoqY3qBQgBJFZppy-3iWkFqqKgSxCPundF8gdDLC5ddizl~KYcYKl42y9SGFHIukH-TZs8~em0~iahzsqWVRks3zRG~tlBcX2U3M2~OJs~C33-NKhyfZT7-XFBREvb8Szmd~p66jDxrwOnKaku-G6DyoQipJqIz4VHmY9-y5T8RrUcJcM-5lVoMpAAAA.i2p/announce.php=http://tracker.mastertracker.i2p/"
     106//       , "Galen", "http://5jpwQMI5FT303YwKa5Rd38PYSX04pbIKgTaKQsWbqoWjIfoancFdWCShXHLI5G5ofOb0Xu11vl2VEMyPsg1jUFYSVnu4-VfMe3y4TKTR6DTpetWrnmEK6m2UXh91J5DZJAKlgmO7UdsFlBkQfR2rY853-DfbJtQIFl91tbsmjcA5CGQi4VxMFyIkBzv-pCsuLQiZqOwWasTlnzey8GcDAPG1LDcvfflGV~6F5no9mnuisZPteZKlrv~~TDoXTj74QjByWc4EOYlwqK8sbU9aOvz~s31XzErbPTfwiawiaZ0RUI-IDrKgyvmj0neuFTWgjRGVTH8bz7cBZIc3viy6ioD-eMQOrXaQL0TCWZUelRwHRvgdPiQrxdYQs7ixkajeHzxi-Pq0EMm5Vbh3j3Q9kfUFW3JjFDA-MLB4g6XnjCbM5J1rC0oOBDCIEfhQkszru5cyLjHiZ5yeA0VThgu~c7xKHybv~OMXION7V8pBKOgET7ZgAkw1xgYe3Kkyq5syAAAA.i2p/tr/announce.php=http://galen.i2p/tr/"
     107       "Postman", "http://tracker2.postman.i2p/announce.php=http://tracker2.postman.i2p/"
     108       ,"Welterde", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
     109       ,"Diftracker", "http://n--XWjHjUPjnMNrSwXA2OYXpMIUL~u4FNXnrt2HtjK3y6j~4SOClyyeKzd0zRPlixxkCe2wfBIYye3bZsaqAD8bd0QMmowxbq91WpjsPfKMiphJbePKXtYAVARiy0cqyvh1d2LyDE-6wkvgaw45hknmS0U-Dg3YTJZbAQRU2SKXgIlAbWCv4R0kDFBLEVpReDiJef3rzAWHiW8yjmJuJilkYjMwlfRjw8xx1nl2s~yhlljk1pl13jGYb0nfawQnuOWeP-ASQWvAAyVgKvZRJE2O43S7iveu9piuv7plXWbt36ef7ndu2GNoNyPOBdpo9KUZ-NOXm4Kgh659YtEibL15dEPAOdxprY0sYUurVw8OIWqrpX7yn08nbi6qHVGqQwTpxH35vkL8qrCbm-ym7oQJQnNmSDrNTyWYRFSq5s5~7DAdFDzqRPW-pX~g0zEivWj5tzkhvG9rVFgFo0bpQX3X0PUAV9Xbyf8u~v8Zbr9K1pCPqBq9XEr4TqaLHw~bfAAAA.i2p/announce.php=http://diftracker.i2p/"
     110//       , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
     111//       ,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
     112    };
     113   
     114    /** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
     115    public static final String PROP_TRACKERS = "i2psnark.trackers";
     116
     117    private static final SnarkManager _instance = new SnarkManager();
     118
     119    public static SnarkManager instance() { return _instance; }
     120
    92121    private SnarkManager() {
    93122        _snarks = new ConcurrentHashMap();
     
    101130        if (!_configFile.isAbsolute())
    102131            _configFile = new File(_context.getConfigDir(), CONFIG_FILE);
     132        _trackerMap = Collections.synchronizedMap(new TreeMap(new IgnoreCaseComparator()));
    103133        loadConfig(null);
    104134    }
     
    313343        _util.setUseOpenTrackers(bOT);
    314344        getDataDir().mkdirs();
     345        initTrackerMap();
    315346    }
    316347   
     
    664695
    665696                    if (!TrackerClient.isValidAnnounce(info.getAnnounce())) {
    666                         if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) {
     697                        if (info.isPrivate()) {
     698                            addMessage(_("ERROR - No I2P trackers in private torrent \"{0}\"", info.getName()));
     699                        } else if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) {
    667700                            //addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
    668701                            addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName()));
     
    13571390
    13581391    /**
    1359      *  "name", "announceURL=websiteURL" pairs
    1360      */
    1361     private static final String DEFAULT_TRACKERS[] = {
    1362 //       "Postman", "http://YRgrgTLGnbTq2aZOZDJQ~o6Uk5k6TK-OZtx0St9pb0G-5EGYURZioxqYG8AQt~LgyyI~NCj6aYWpPO-150RcEvsfgXLR~CxkkZcVpgt6pns8SRc3Bi-QSAkXpJtloapRGcQfzTtwllokbdC-aMGpeDOjYLd8b5V9Im8wdCHYy7LRFxhEtGb~RL55DA8aYOgEXcTpr6RPPywbV~Qf3q5UK55el6Kex-6VCxreUnPEe4hmTAbqZNR7Fm0hpCiHKGoToRcygafpFqDw5frLXToYiqs9d4liyVB-BcOb0ihORbo0nS3CLmAwZGvdAP8BZ7cIYE3Z9IU9D1G8JCMxWarfKX1pix~6pIA-sp1gKlL1HhYhPMxwyxvuSqx34o3BqU7vdTYwWiLpGM~zU1~j9rHL7x60pVuYaXcFQDR4-QVy26b6Pt6BlAZoFmHhPcAuWfu-SFhjyZYsqzmEmHeYdAwa~HojSbofg0TMUgESRXMw6YThK1KXWeeJVeztGTz25sL8AAAA.i2p/announce.php=http://tracker.postman.i2p/"
    1363 //       , "eBook", "http://E71FRom6PZNEqTN2Lr8P-sr23b7HJVC32KoGnVQjaX6zJiXwhJy2HsXob36Qmj81TYFZdewFZa9mSJ533UZgGyQkXo2ahctg82JKYZfDe5uDxAn1E9YPjxZCWJaFJh0S~UwSs~9AZ7UcauSJIoNtpxrtbmRNVFLqnkEDdLZi26TeucfOmiFmIWnVblLniWv3tG1boE9Abd-6j3FmYVrRucYuepAILYt6katmVNOk6sXmno1Eynrp~~MBuFq0Ko6~jsc2E2CRVYXDhGHEMdt-j6JUz5D7S2RIVzDRqQyAZLKJ7OdQDmI31przzmne1vOqqqLC~1xUumZVIvF~yOeJUGNjJ1Vx0J8i2BQIusn1pQJ6UCB~ZtZZLQtEb8EPVCfpeRi2ri1M5CyOuxN0V5ekmPHrYIBNevuTCRC26NP7ZS5VDgx1~NaC3A-CzJAE6f1QXi0wMI9aywNG5KGzOPifcsih8eyGyytvgLtrZtV7ykzYpPCS-rDfITncpn5hliPUAAAA.i2p/pub/bt/announce.php=http://de-ebook-archiv.i2p/pub/bt/"
    1364 //       , "Gaytorrents", "http://uxPWHbK1OIj9HxquaXuhMiIvi21iK0~ZiG9d8G0840ZXIg0r6CbiV71xlsqmdnU6wm0T2LySriM0doW2gUigo-5BNkUquHwOjLROiETnB3ZR0Ml4IGa6QBPn1aAq2d9~g1r1nVjLE~pcFnXB~cNNS7kIhX1d6nLgYVZf0C2cZopEow2iWVUggGGnAA9mHjE86zLEnTvAyhbAMTqDQJhEuLa0ZYSORqzJDMkQt90MV4YMjX1ICY6RfUSFmxEqu0yWTrkHsTtRw48l~dz9wpIgc0a0T9C~eeWvmBFTqlJPtQZwntpNeH~jF7nlYzB58olgV2HHFYpVYD87DYNzTnmNWxCJ5AfDorm6AIUCV2qaE7tZtI1h6fbmGpGlPyW~Kw5GXrRfJwNvr6ajwAVi~bPVnrBwDZezHkfW4slOO8FACPR28EQvaTu9nwhAbqESxV2hCTq6vQSGjuxHeOuzBOEvRWkLKOHWTC09t2DbJ94FSqETmZopTB1ukEmaxRWbKSIaAAAA.i2p/announce.php=http://gaytorrents.i2p/"
    1365 //       , "NickyB", "http://9On6d3cZ27JjwYCtyJJbowe054d5tFnfMjv4PHsYs-EQn4Y4mk2zRixatvuAyXz2MmRfXG-NAUfhKr0KCxRNZbvHmlckYfT-WBzwwpiMAl0wDFY~Pl8cqXuhfikSG5WrqdPfDNNIBuuznS0dqaczf~OyVaoEOpvuP3qV6wKqbSSLpjOwwAaQPHjlRtNIW8-EtUZp-I0LT45HSoowp~6b7zYmpIyoATvIP~sT0g0MTrczWhbVTUZnEkZeLhOR0Duw1-IRXI2KHPbA24wLO9LdpKKUXed05RTz0QklW5ROgR6TYv7aXFufX8kC0-DaKvQ5JKG~h8lcoHvm1RCzNqVE-2aiZnO2xH08H-iCWoLNJE-Td2kT-Tsc~3QdQcnEUcL5BF-VT~QYRld2--9r0gfGl-yDrJZrlrihHGr5J7ImahelNn9PpkVp6eIyABRmJHf2iicrk3CtjeG1j9OgTSwaNmEpUpn4aN7Kx0zNLdH7z6uTgCGD9Kmh1MFYrsoNlTp4AAAA.i2p/bittorrent/announce.php=http://nickyb.i2p/bittorrent/"
    1366 //       , "Orion", "http://gKik1lMlRmuroXVGTZ~7v4Vez3L3ZSpddrGZBrxVriosCQf7iHu6CIk8t15BKsj~P0JJpxrofeuxtm7SCUAJEr0AIYSYw8XOmp35UfcRPQWyb1LsxUkMT4WqxAT3s1ClIICWlBu5An~q-Mm0VFlrYLIPBWlUFnfPR7jZ9uP5ZMSzTKSMYUWao3ejiykr~mtEmyls6g-ZbgKZawa9II4zjOy-hdxHgP-eXMDseFsrym4Gpxvy~3Fv9TuiSqhpgm~UeTo5YBfxn6~TahKtE~~sdCiSydqmKBhxAQ7uT9lda7xt96SS09OYMsIWxLeQUWhns-C~FjJPp1D~IuTrUpAFcVEGVL-BRMmdWbfOJEcWPZ~CBCQSO~VkuN1ebvIOr9JBerFMZSxZtFl8JwcrjCIBxeKPBmfh~xYh16BJm1BBBmN1fp2DKmZ2jBNkAmnUbjQOqWvUcehrykWk5lZbE7bjJMDFH48v3SXwRuDBiHZmSbsTY6zhGY~GkMQHNGxPMMSIAAAA.i2p/bt/announce.php=http://orion.i2p/bt/"
    1367 //       , "anonymity", "http://8EoJZIKrWgGuDrxA3nRJs1jsPfiGwmFWL91hBrf0HA7oKhEvAna4Ocx47VLUR9retVEYBAyWFK-eZTPcvhnz9XffBEiJQQ~kFSCqb1fV6IfPiV3HySqi9U5Caf6~hC46fRd~vYnxmaBLICT3N160cxBETqH3v2rdxdJpvYt8q4nMk9LUeVXq7zqCTFLLG5ig1uKgNzBGe58iNcsvTEYlnbYcE930ABmrzj8G1qQSgSwJ6wx3tUQNl1z~4wSOUMan~raZQD60lRK70GISjoX0-D0Po9WmPveN3ES3g72TIET3zc3WPdK2~lgmKGIs8GgNLES1cXTolvbPhdZK1gxddRMbJl6Y6IPFyQ9o4-6Rt3Lp-RMRWZ2TG7j2OMcNSiOmATUhKEFBDfv-~SODDyopGBmfeLw16F4NnYednvn4qP10dyMHcUASU6Zag4mfc2-WivrOqeWhD16fVAh8MoDpIIT~0r9XmwdaVFyLcjbXObabJczxCAW3fodQUnvuSkwzAAAA.i2p/anonymityTracker/announce.php=http://anonymityweb.i2p/anonymityTracker/"
    1368 //       , "The freak's tracker", "http://mHKva9x24E5Ygfey2llR1KyQHv5f8hhMpDMwJDg1U-hABpJ2NrQJd6azirdfaR0OKt4jDlmP2o4Qx0H598~AteyD~RJU~xcWYdcOE0dmJ2e9Y8-HY51ie0B1yD9FtIV72ZI-V3TzFDcs6nkdX9b81DwrAwwFzx0EfNvK1GLVWl59Ow85muoRTBA1q8SsZImxdyZ-TApTVlMYIQbdI4iQRwU9OmmtefrCe~ZOf4UBS9-KvNIqUL0XeBSqm0OU1jq-D10Ykg6KfqvuPnBYT1BYHFDQJXW5DdPKwcaQE4MtAdSGmj1epDoaEBUa9btQlFsM2l9Cyn1hzxqNWXELmx8dRlomQLlV4b586dRzW~fLlOPIGC13ntPXogvYvHVyEyptXkv890jC7DZNHyxZd5cyrKC36r9huKvhQAmNABT2Y~pOGwVrb~RpPwT0tBuPZ3lHYhBFYmD8y~AOhhNHKMLzea1rfwTvovBMByDdFps54gMN1mX4MbCGT4w70vIopS9yAAAA.i2p/bytemonsoon/announce.php"
    1369 //       , "mastertracker", "http://VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT8JD7i-C2xzYFa4jT5U2aqHzHI-Jre4HL3Ri5hFtZrLk2ax3ji7Qfb6qPnuYkuiF2E2UDmKUOppI8d9Ye7tjdhQVCy0izn55tBaB-U7UWdcvSK2i85sauyw3G0Gfads1Rvy5-CAe2paqyYATcDmGjpUNLoxbfv9KH1KmwRTNH6k1v4PyWYYnhbT39WfKMbBjSxVQRdi19cyJrULSWhjxaQfJHeWx5Z8Ev4bSPByBeQBFl2~4vqy0S5RypINsRSa3MZdbiAAyn5tr5slWR6QdoqY3qBQgBJFZppy-3iWkFqqKgSxCPundF8gdDLC5ddizl~KYcYKl42y9SGFHIukH-TZs8~em0~iahzsqWVRks3zRG~tlBcX2U3M2~OJs~C33-NKhyfZT7-XFBREvb8Szmd~p66jDxrwOnKaku-G6DyoQipJqIz4VHmY9-y5T8RrUcJcM-5lVoMpAAAA.i2p/announce.php=http://tracker.mastertracker.i2p/"
    1370 //       , "Galen", "http://5jpwQMI5FT303YwKa5Rd38PYSX04pbIKgTaKQsWbqoWjIfoancFdWCShXHLI5G5ofOb0Xu11vl2VEMyPsg1jUFYSVnu4-VfMe3y4TKTR6DTpetWrnmEK6m2UXh91J5DZJAKlgmO7UdsFlBkQfR2rY853-DfbJtQIFl91tbsmjcA5CGQi4VxMFyIkBzv-pCsuLQiZqOwWasTlnzey8GcDAPG1LDcvfflGV~6F5no9mnuisZPteZKlrv~~TDoXTj74QjByWc4EOYlwqK8sbU9aOvz~s31XzErbPTfwiawiaZ0RUI-IDrKgyvmj0neuFTWgjRGVTH8bz7cBZIc3viy6ioD-eMQOrXaQL0TCWZUelRwHRvgdPiQrxdYQs7ixkajeHzxi-Pq0EMm5Vbh3j3Q9kfUFW3JjFDA-MLB4g6XnjCbM5J1rC0oOBDCIEfhQkszru5cyLjHiZ5yeA0VThgu~c7xKHybv~OMXION7V8pBKOgET7ZgAkw1xgYe3Kkyq5syAAAA.i2p/tr/announce.php=http://galen.i2p/tr/"
    1371        "Postman", "http://tracker2.postman.i2p/announce.php=http://tracker2.postman.i2p/"
    1372        ,"Welterde", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
    1373        ,"Diftracker", "http://n--XWjHjUPjnMNrSwXA2OYXpMIUL~u4FNXnrt2HtjK3y6j~4SOClyyeKzd0zRPlixxkCe2wfBIYye3bZsaqAD8bd0QMmowxbq91WpjsPfKMiphJbePKXtYAVARiy0cqyvh1d2LyDE-6wkvgaw45hknmS0U-Dg3YTJZbAQRU2SKXgIlAbWCv4R0kDFBLEVpReDiJef3rzAWHiW8yjmJuJilkYjMwlfRjw8xx1nl2s~yhlljk1pl13jGYb0nfawQnuOWeP-ASQWvAAyVgKvZRJE2O43S7iveu9piuv7plXWbt36ef7ndu2GNoNyPOBdpo9KUZ-NOXm4Kgh659YtEibL15dEPAOdxprY0sYUurVw8OIWqrpX7yn08nbi6qHVGqQwTpxH35vkL8qrCbm-ym7oQJQnNmSDrNTyWYRFSq5s5~7DAdFDzqRPW-pX~g0zEivWj5tzkhvG9rVFgFo0bpQX3X0PUAV9Xbyf8u~v8Zbr9K1pCPqBq9XEr4TqaLHw~bfAAAA.i2p/announce.php=http://diftracker.i2p/"
    1374 //       , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
    1375 //       ,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
    1376     };
    1377    
    1378     /** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
    1379     public static final String PROP_TRACKERS = "i2psnark.trackers";
    1380     private static Map<String, String> trackerMap = null;
    1381     /** sorted map of name to announceURL=baseURL */
     1392     *  Sorted map of name to announceURL=baseURL
     1393     *  Modifiable, not a copy
     1394     */
    13821395    public Map<String, String> getTrackers() {
    1383         if (trackerMap != null) // only do this once, can't be updated while running
    1384             return trackerMap;
    1385         Map<String, String> rv = new TreeMap();
     1396        return _trackerMap;
     1397    }
     1398
     1399    /** @since 0.9 */
     1400    private void initTrackerMap() {
    13861401        String trackers = _config.getProperty(PROP_TRACKERS);
    13871402        if ( (trackers == null) || (trackers.trim().length() <= 0) )
    13881403            trackers = _context.getProperty(PROP_TRACKERS);
     1404        _trackerMap.clear();
    13891405        if ( (trackers == null) || (trackers.trim().length() <= 0) ) {
    13901406            for (int i = 0; i < DEFAULT_TRACKERS.length; i += 2)
    1391                 rv.put(DEFAULT_TRACKERS[i], DEFAULT_TRACKERS[i+1]);
     1407                _trackerMap.put(DEFAULT_TRACKERS[i], DEFAULT_TRACKERS[i+1]);
    13921408        } else {
    1393             StringTokenizer tok = new StringTokenizer(trackers, ",");
    1394             while (tok.hasMoreTokens()) {
    1395                 String pair = tok.nextToken();
    1396                 int split = pair.indexOf('=');
    1397                 if (split <= 0)
    1398                     continue;
    1399                 String name = pair.substring(0, split).trim();
    1400                 String url = pair.substring(split+1).trim();
     1409            String[] toks = trackers.split(",");
     1410            for (int i = 0; i < toks.length; i += 2) {
     1411                String name = toks[i].trim().replace("&#44;", ",");
     1412                String url = toks[i+1].trim().replace("&#44;", ",");
    14011413                if ( (name.length() > 0) && (url.length() > 0) )
    1402                     rv.put(name, url);
    1403             }
    1404         }
    1405        
    1406         trackerMap = rv;
    1407         return trackerMap;
    1408     }
    1409    
     1414                    _trackerMap.put(name, url);
     1415            }
     1416        }
     1417    }
     1418
     1419    /** @since 0.9 */
     1420    public void setDefaultTrackerMap() {
     1421        _trackerMap.clear();
     1422        for (int i = 0; i < DEFAULT_TRACKERS.length; i += 2) {
     1423            _trackerMap.put(DEFAULT_TRACKERS[i], DEFAULT_TRACKERS[i+1]);
     1424        }
     1425        if (_config.remove(PROP_TRACKERS) != null) {
     1426            saveConfig();
     1427        }
     1428    }
     1429
     1430    /** @since 0.9 */
     1431    public void saveTrackerMap() {
     1432        StringBuilder buf = new StringBuilder(2048);
     1433        boolean comma = false;
     1434        for (Map.Entry<String, String> e : _trackerMap.entrySet()) {
     1435            if (comma)
     1436                buf.append(',');
     1437            else
     1438                comma = true;
     1439            buf.append(e.getKey().replace(",", "&#44;")).append(',').append(e.getValue().replace(",", "&#44;"));
     1440        }
     1441        _config.setProperty(PROP_TRACKERS, buf.toString());
     1442        saveConfig();
     1443    }
     1444
    14101445    private static class TorrentFilenameFilter implements FilenameFilter {
    14111446        private static final TorrentFilenameFilter _filter = new TorrentFilenameFilter();
     
    14271462        }
    14281463    }
     1464
     1465    /**
     1466     *  ignore case, current locale
     1467     *  @since 0.9
     1468     */
     1469    private static class IgnoreCaseComparator implements Comparator<String> {
     1470        public int compare(String l, String r) {
     1471            return l.toLowerCase().compareTo(r.toLowerCase());
     1472        }
     1473    }
    14291474}
  • apps/i2psnark/java/src/org/klomp/snark/Storage.java

    rf43b0be r2b81cee  
    102102   * @param listener may be null
    103103   */
    104   public Storage(I2PSnarkUtil util, File baseFile, String announce, StorageListener listener)
     104  public Storage(I2PSnarkUtil util, File baseFile, String announce,
     105                 boolean privateTorrent, StorageListener listener)
    105106    throws IOException
    106107  {
     
    158159    byte[] piece_hashes = fast_digestCreate();
    159160    metainfo = new MetaInfo(announce, baseFile.getName(), null, files,
    160                             lengthsList, piece_size, piece_hashes, total);
     161                            lengthsList, piece_size, piece_hashes, total, privateTorrent);
    161162
    162163  }
  • apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java

    rf43b0be r2b81cee  
    157157    }
    158158    List tlist = _util.getOpenTrackers();
    159     if (tlist != null) {
     159    if (tlist != null && !meta.isPrivate()) {
    160160        for (int i = 0; i < tlist.size(); i++) {
    161161             String url = (String)tlist.get(i);
     
    349349
    350350            // Get peers from PEX
    351             if (left > 0 && coordinator.needPeers() && !stop) {
     351            if (left > 0 && coordinator.needPeers() && (!meta.isPrivate()) && !stop) {
    352352                Set<PeerID> pids = coordinator.getPEXPeers();
    353353                if (!pids.isEmpty()) {
     
    371371            // Get peers from DHT
    372372            // FIXME this needs to be in its own thread
    373             if (_util.getDHT() != null && !stop) {
     373            if (_util.getDHT() != null && (!meta.isPrivate()) && !stop) {
    374374                int numwant;
    375375                if (left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
     
    445445    throws IOException
    446446  {
     447    StringBuilder buf = new StringBuilder(512);
     448    buf.append(tr.announce);
     449    if (tr.announce.contains("?"))
     450        buf.append('&');
     451    else
     452        buf.append('?');
     453    buf.append("info_hash=").append(infoHash)
     454       .append("&peer_id=").append(peerID)
     455       .append("&port=").append(port)
     456       .append("&ip=" ).append(_util.getOurIPString()).append(".i2p")
     457       .append("&uploaded=").append(uploaded)
     458       .append("&downloaded=").append(downloaded)
     459       .append("&left=");
    447460    // What do we send for left in magnet mode? Can we omit it?
    448     long tleft = left >= 0 ? left : 1;
    449     String s = tr.announce
    450       + "?info_hash=" + infoHash
    451       + "&peer_id=" + peerID
    452       + "&port=" + port
    453       + "&ip=" + _util.getOurIPString() + ".i2p"
    454       + "&uploaded=" + uploaded
    455       + "&downloaded=" + downloaded
    456       + "&left=" + tleft
    457       + "&compact=1"   // NOTE: opentracker will return 400 for &compact alone
    458       + ((! event.equals(NO_EVENT)) ? ("&event=" + event) : "");
     461    if (left >= 0)
     462        buf.append(left);
     463    else
     464        buf.append('1');
     465    buf.append("&compact=1");  // NOTE: opentracker will return 400 for &compact alone
     466    if (! event.equals(NO_EVENT))
     467        buf.append("&event=").append(event);
     468    buf.append("&numwant=");
    459469    if (left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
    460         s += "&numwant=0";
     470        buf.append('0');
    461471    else
    462         s += "&numwant=" + _util.getMaxConnections();
     472        buf.append(_util.getMaxConnections());
     473    String s = buf.toString();
    463474    _util.debug("Sending TrackerClient request: " + s, Snark.INFO);
    464475     
  • apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java

    rf43b0be r2b81cee  
    102102    {
    103103        if (pathInContext == null || pathInContext.equals("/") || pathInContext.equals("/index.jsp") ||
    104             pathInContext.equals("/index.html") || pathInContext.startsWith("/_icons/"))
     104            pathInContext.equals("/index.html") || pathInContext.startsWith("/.icons/") ||
     105            pathInContext.startsWith("/.js/") || pathInContext.startsWith("/.ajax/"))
    105106            return super.getResource(pathInContext);
    106107        // files in the i2psnark/ directory
     
    156157        // this is the part after /i2psnark
    157158        String path = req.getServletPath();
     159
     160        // AJAX for mainsection
     161        if ("/.ajax/xhr1.html".equals(path)) {
     162            resp.setCharacterEncoding("UTF-8");
     163            resp.setContentType("text/html; charset=UTF-8");
     164            PrintWriter out = resp.getWriter();
     165            //if (_log.shouldLog(Log.DEBUG))
     166            //    _manager.addMessage((_context.clock().now() / 1000) + " xhr1 p=" + req.getParameter("p"));
     167            writeMessages(out);
     168            writeTorrents(out, req);
     169            return;
     170        }
     171
    158172        boolean isConfigure = "/configure".equals(path);
    159173        // index.jsp doesn't work, it is grabbed by the war handler before here
     
    197211        String peerParam = req.getParameter("p");
    198212        String peerString;
    199         if (peerParam == null || !_manager.util().connected()) {
     213        if (peerParam == null || (!_manager.util().connected()) ||
     214            peerParam.replaceAll("[a-zA-Z0-9~=-]", "").length() > 0) {  // XSS
    200215            peerString = "";
    201216        } else {
     
    213228                                         
    214229        // we want it to go to the base URI so we don't refresh with some funky action= value
     230        int delay = 0;
    215231        if (!isConfigure) {
    216             int delay = _manager.getRefreshDelaySeconds();
    217             if (delay > 0)
    218                 out.write("<meta http-equiv=\"refresh\" content=\"" + delay + ";/i2psnark/" + peerString + "\">\n");
    219         }
    220         out.write(HEADER_A + _themePath + HEADER_B);
    221         out.write("</head><body>");
     232            delay = _manager.getRefreshDelaySeconds();
     233            if (delay > 0) {
     234                //out.write("<meta http-equiv=\"refresh\" content=\"" + delay + ";/i2psnark/" + peerString + "\">\n");
     235                out.write("<script src=\"/js/ajax.js\" type=\"text/javascript\"></script>\n" +
     236                          "<script type=\"text/javascript\">\n"  +
     237                          "var failMessage = \"<b>" + _("Router is down") + "</b>\";\n" +
     238                          "function requestAjax1() { ajax(\"/i2psnark/.ajax/xhr1.html" + peerString + "\", \"mainsection\", " + (delay*1000) + "); }\n" +
     239                          "function initAjax(delayMs) { setTimeout(requestAjax1, " + (delay*1000) +");  }\n"  +
     240                          "</script>\n");
     241            }
     242        }
     243        out.write(HEADER_A + _themePath + HEADER_B + "</head>\n");
     244        if (isConfigure || delay <= 0)
     245            out.write("<body>");
     246        else
     247            out.write("<body onload=\"initAjax()\">");
    222248        out.write("<center>");
    223249        if (isConfigure) {
     
    254280        if (newURL != null && newURL.trim().length() > 0 && req.getMethod().equals("GET"))
    255281            _manager.addMessage(_("Click \"Add torrent\" button to fetch torrent"));
    256         out.write("<div class=\"page\"><div class=\"mainsection\"><div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
     282        out.write("<div class=\"page\"><div id=\"mainsection\" class=\"mainsection\">");
     283
     284        writeMessages(out);
     285
     286        if (isConfigure) {
     287            // end of mainsection div
     288            out.write("<div class=\"logshim\"></div></div>\n");
     289            writeConfigForm(out, req);
     290            writeTrackerForm(out, req);
     291        } else {
     292            writeTorrents(out, req);
     293            // end of mainsection div
     294            out.write("</div><div id=\"lowersection\">\n");
     295            writeAddForm(out, req);
     296            writeSeedForm(out, req);
     297            writeConfigLink(out);
     298            // end of lowersection div
     299            out.write("</div>\n");
     300        }
     301        out.write(FOOTER);
     302    }
     303
     304    private void writeMessages(PrintWriter out) throws IOException {
     305        out.write("<div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
    257306        List msgs = _manager.getMessages();
    258307        for (int i = msgs.size()-1; i >= 0; i--) {
     
    261310        }
    262311        out.write("</pre></td></tr></table></div>");
    263 
    264         if (isConfigure) {
    265             out.write("<div class=\"logshim\"></div></div>\n");
    266             writeConfigForm(out, req);
    267         } else {
    268             writeTorrents(out, req);
    269             out.write("</div>\n");
    270             writeAddForm(out, req);
    271             writeSeedForm(out, req);
    272             writeConfigLink(out);
    273         }
    274         out.write(FOOTER);
    275312    }
    276313
     
    281318
    282319        List snarks = getSortedSnarks(req);
    283         String uri = req.getRequestURI();
    284320        boolean isForm = _manager.util().connected() || !snarks.isEmpty();
    285321        if (isForm) {
     
    395431        }
    396432        out.write("</th></tr></thead>\n");
     433        String uri = "/i2psnark/";
    397434        for (int i = 0; i < snarks.size(); i++) {
    398435            Snark snark = (Snark)snarks.get(i);
     
    655692                                  seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts,
    656693                                  upLimit, upBW, useOpenTrackers, openTrackers, theme);
     694        } else if ("Save2".equals(action)) {
     695            String taction = req.getParameter("taction");
     696            if (taction != null)
     697                processTrackerForm(taction, req);
    657698        } else if ("Create".equals(action)) {
    658699            String baseData = req.getParameter("baseFile");
     
    660701                File baseFile = new File(_manager.getDataDir(), baseData);
    661702                String announceURL = req.getParameter("announceURL");
    662                 String announceURLOther = req.getParameter("announceURLOther");
    663                 if ( (announceURLOther != null) && (announceURLOther.trim().length() > "http://.i2p/announce".length()) )
    664                     announceURL = announceURLOther;
     703                // make the user add a tracker on the config form now
     704                //String announceURLOther = req.getParameter("announceURLOther");
     705                //if ( (announceURLOther != null) && (announceURLOther.trim().length() > "http://.i2p/announce".length()) )
     706                //    announceURL = announceURLOther;
    665707
    666708                if (announceURL == null || announceURL.length() <= 0)
     
    673715                        // This may take a long time to check the storage, but since it already exists,
    674716                        // it shouldn't be THAT bad, so keep it in this thread.
    675                         Storage s = new Storage(_manager.util(), baseFile, announceURL, null);
     717                        Storage s = new Storage(_manager.util(), baseFile, announceURL, req.getParameter("private") != null, null);
    676718                        s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
    677719                        MetaInfo info = s.getMetaInfo();
     
    714756                    snark.startTorrent();
    715757            }
     758        } else {
     759            _manager.addMessage("Unknown POST action: \"" + action + '\"');
     760        }
     761    }
     762
     763    /** @since 0.9 */
     764    private void processTrackerForm(String action, HttpServletRequest req) {
     765        if (action.equals(_("Delete selected"))) {
     766            boolean changed = false;
     767            Map<String, String> trackers = _manager.getTrackers();
     768            Enumeration e = req.getParameterNames();
     769            while (e.hasMoreElements()) {
     770                 Object o = e.nextElement();
     771                 if (!(o instanceof String))
     772                     continue;
     773                 String k = (String) o;
     774                 if (!k.startsWith("delete_"))
     775                     continue;
     776                 k = k.substring(7);
     777                 if (trackers.remove(k) != null) {
     778                    _manager.addMessage(_("Removed") + ": " + k);
     779                    changed = true;
     780                }
     781            }
     782            if (changed) {
     783                _manager.saveTrackerMap();
     784            }
     785        } else if (action.equals(_("Add tracker"))) {
     786            String name = req.getParameter("tname");
     787            String hurl = req.getParameter("thurl");
     788            String aurl = req.getParameter("taurl");
     789            if (name != null && hurl != null && aurl != null) {
     790                name = name.trim();
     791                hurl = hurl.trim();
     792                aurl = aurl.trim().replace("=", "&#61;");
     793                if (name.length() > 0 && hurl.startsWith("http://") && aurl.startsWith("http://")) {
     794                    Map<String, String> trackers = _manager.getTrackers();
     795                    trackers.put(name, aurl + '=' + hurl);
     796                    _manager.saveTrackerMap();
     797                } else {
     798                    _manager.addMessage(_("Enter valid tracker name and URLs"));
     799                }
     800            } else {
     801                _manager.addMessage(_("Enter valid tracker name and URLs"));
     802            }
     803        } else if (action.equals(_("Restore defaults"))) {
     804            _manager.setDefaultTrackerMap();
     805            _manager.addMessage(_("Restored default trackers"));
    716806        } else {
    717807            _manager.addMessage("Unknown POST action: \"" + action + '\"');
     
    12271317        // not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve)
    12281318        //out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>");
    1229         out.write("<input type=\"submit\" value=\"");
     1319        out.write("<input type=\"submit\" class=\"add\" value=\"");
    12301320        out.write(_("Add torrent"));
    12311321        out.write("\" name=\"foo\" ><br>\n");
     
    12741364        out.write(_("Open trackers only"));
    12751365        out.write("</option>\n");
    1276         Map trackers = _manager.getTrackers();
    1277         for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
    1278             Map.Entry entry = (Map.Entry)iter.next();
    1279             String name = (String)entry.getKey();
    1280             String announceURL = (String)entry.getValue();
     1366        Map<String, String> trackers = _manager.getTrackers();
     1367        for (Map.Entry<String, String> entry : trackers.entrySet()) {
     1368            String name = entry.getKey();
     1369            String announceURL = entry.getValue();
    12811370            int e = announceURL.indexOf('=');
    12821371            if (e > 0)
    1283                 announceURL = announceURL.substring(0, e);
     1372                announceURL = announceURL.substring(0, e).replace("&#61;", "=");
    12841373            if (announceURL.equals(_lastAnnounceURL))
    12851374                announceURL += "\" selected=\"selected";
     
    12871376        }
    12881377        out.write("</select>\n");
    1289         out.write(_("or"));
    1290         out.write("&nbsp;<input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
    1291                   "title=\"");
    1292         out.write(_("Specify custom tracker announce URL"));
    1293         out.write("\" > " +
    1294                   "<input type=\"submit\" value=\"");
     1378        // make the user add a tracker on the config form now
     1379        //out.write(_("or"));
     1380        //out.write("&nbsp;<input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
     1381        //          "title=\"");
     1382        //out.write(_("Specify custom tracker announce URL"));
     1383        //out.write("\" > " +
     1384        out.write(" <input type=\"submit\" class=\"create\" value=\"");
    12951385        out.write(_("Create torrent"));
    1296         out.write("\" name=\"foo\" ></table>\n" +
     1386        out.write("\" name=\"foo\" >\n" +
     1387                  "</td></tr><tr><td>");
     1388        out.write(_("Private?"));
     1389        out.write(" </td><td> <input type=\"checkbox\" class=\"optbox\" name=\"private\" value=\"true\" title=\"");
     1390            out.write(_("Use for private trackers"));
     1391        out.write("\"");
     1392        if (req.getParameter("private") != null)
     1393            out.write(" checked");
     1394        out.write("></td></tr>" +
     1395                  "</table>\n" +
    12971396                  "</form></div></div>");       
    12981397    }
    12991398   
    1300     private static final int[] times = { 30, 60, 2*60, 5*60, 10*60, 30*60, -1 };
     1399    private static final int[] times = { 5, 15, 30, 60, 2*60, 5*60, 10*60, 30*60, -1 };
    13011400
    13021401    private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException {
     
    13611460            out.write("\"");
    13621461            if (times[i] == delay)
    1363                 out.write(" selected=\"true\"");
     1462                out.write(" selected=\"selected\"");
    13641463            out.write(">");
    13651464            if (times[i] > 0)
     
    13841483        out.write("Seed percentage: <select name=\"seedPct\" disabled=\"true\" >\n\t");
    13851484        if (seedPct <= 0)
    1386             out.write("<option value=\"0\" selected=\"true\">Unlimited</option>\n\t");
     1485            out.write("<option value=\"0\" selected=\"selected\">Unlimited</option>\n\t");
    13871486        else
    13881487            out.write("<option value=\"0\">Unlimited</option>\n\t");
    13891488        if (seedPct == 100)
    1390             out.write("<option value=\"100\" selected=\"true\">100%</option>\n\t");
     1489            out.write("<option value=\"100\" selected=\"selected\">100%</option>\n\t");
    13911490        else
    13921491            out.write("<option value=\"100\">100%</option>\n\t");
    13931492        if (seedPct == 150)
    1394             out.write("<option value=\"150\" selected=\"true\">150%</option>\n\t");
     1493            out.write("<option value=\"150\" selected=\"selected\">150%</option>\n\t");
    13951494        else
    13961495            out.write("<option value=\"150\">150%</option>\n\t");
     
    14781577    }
    14791578   
     1579    /** @since 0.9 */
     1580    private void writeTrackerForm(PrintWriter out, HttpServletRequest req) throws IOException {
     1581        StringBuilder buf = new StringBuilder(1024);
     1582        buf.append("<form action=\"/i2psnark/configure\" method=\"POST\">\n" +
     1583                  "<div class=\"configsectionpanel\"><div class=\"snarkConfig\">\n" +
     1584                  "<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n" +
     1585                  "<input type=\"hidden\" name=\"action\" value=\"Save2\" >\n" +
     1586                  "<span class=\"snarkConfigTitle\">" +
     1587                  "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
     1588        buf.append(_("Trackers"));
     1589        buf.append("</span><hr>\n"   +
     1590                   "<table><tr><th>")
     1591           //.append(_("Remove"))
     1592           .append("</th><th>")
     1593           .append(_("Name"))
     1594           .append("</th><th>")
     1595           .append(_("Website URL"))
     1596           .append("</th><th>")
     1597           .append(_("Announce URL"))
     1598           .append("</th></tr>\n");
     1599        Map<String, String> trackers = _manager.getTrackers();
     1600        for (Map.Entry<String, String> entry : trackers.entrySet()) {
     1601            String name = entry.getKey();
     1602            String announceURL = entry.getValue();
     1603            int e = announceURL.indexOf('=');
     1604            if (e <= 0)
     1605                continue;
     1606            String homeURL = announceURL.substring(e + 1);
     1607            announceURL = announceURL.substring(0, e).replace("&#61;", "=");
     1608            buf.append("<tr><td align=\"center\"><input type=\"checkbox\" class=\"optbox\" name=\"delete_")
     1609               .append(name).append("\">" +
     1610                       "</td><td align=\"left\">").append(name)
     1611               .append("</td><td align=\"left\">").append(urlify(homeURL, 35))
     1612               .append("</td><td align=\"left\">").append(urlify(announceURL, 35))
     1613               .append("</td></tr>\n");
     1614        }
     1615        buf.append("<tr><td align=\"center\"><b>")
     1616           .append(_("Add")).append(":</b></td>" +
     1617                   "<td align=\"left\"><input type=\"text\" size=\"16\" name=\"tname\"></td>" +
     1618                   "<td align=\"left\"><input type=\"text\" size=\"40\" name=\"thurl\"></td>" +
     1619                   "<td align=\"left\"><input type=\"text\" size=\"40\" name=\"taurl\"></td></tr>\n" +
     1620                   "<tr><td colspan=\"2\"></td><td colspan=\"2\" align=\"left\">\n" +
     1621                   "<input type=\"submit\" name=\"taction\" class=\"default\" value=\"").append(_("Add tracker")).append("\">\n" +
     1622                   "<input type=\"submit\" name=\"taction\" class=\"delete\" value=\"").append(_("Delete selected")).append("\">\n" +
     1623                   // "<input type=\"reset\" class=\"cancel\" value=\"").append(_("Cancel")).append("\">\n" +
     1624                   "<input type=\"submit\" name=\"taction\" class=\"reload\" value=\"").append(_("Restore defaults")).append("\">\n" +
     1625                   "<input type=\"submit\" name=\"taction\" class=\"add\" value=\"").append(_("Add tracker")).append("\">\n" +
     1626                   "</td></tr></table></div></div></form>\n");
     1627        out.write(buf.toString());
     1628    }
     1629
    14801630    private void writeConfigLink(PrintWriter out) throws IOException {
    14811631        out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n" +
     
    15791729            buf.append("<option value=\"").append(i).append("\" ");
    15801730            if (i == now)
    1581                 buf.append("selected=\"true\" ");
     1731                buf.append("selected=\"selected\" ");
    15821732            // constants to prevent tagging
    15831733            buf.append(">").append(ngettext(DUMMY1 + name, DUMMY0 + name + 's', i));
     
    16271777    /** @since 0.7.14 */
    16281778    private static String urlify(String s) {
     1779        return urlify(s, 100);
     1780    }
     1781   
     1782    /** @since 0.9 */
     1783    private static String urlify(String s, int max) {
    16291784        StringBuilder buf = new StringBuilder(256);
    16301785        // browsers seem to work without doing this but let's be strict
    16311786        String link = urlEncode(s);
    1632         buf.append("<a href=\"").append(link).append("\">").append(link).append("</a>");
     1787        String display;
     1788        if (s.length() <= max)
     1789            display = link;
     1790        else
     1791            display = urlEncode(s.substring(0, max)) + "&hellip;";
     1792        buf.append("<a href=\"").append(link).append("\">").append(display).append("</a>");
    16331793        return buf.toString();
    16341794    }
     
    19962156    /** @since 0.7.14 */
    19972157    private static String toImg(String icon) {
    1998         return "<img alt=\"\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\">";
     2158        return "<img alt=\"\" height=\"16\" width=\"16\" src=\"/i2psnark/.icons/" + icon + ".png\">";
    19992159    }
    20002160
    20012161    /** @since 0.8.2 */
    20022162    private static String toImg(String icon, String altText) {
    2003         return "<img alt=\"" + altText + "\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\">";
     2163        return "<img alt=\"" + altText + "\" height=\"16\" width=\"16\" src=\"/i2psnark/.icons/" + icon + ".png\">";
    20042164    }
    20052165
  • apps/i2ptunnel/java/build.xml

    rf43b0be r2b81cee  
    6262                <attribute name="Class-Path" value="i2p.jar mstreaming.jar" />
    6363                <attribute name="Implementation-Version" value="${full.version}" />
     64                <attribute name="Built-By" value="${build.built-by}" />
    6465                <attribute name="Build-Date" value="${build.timestamp}" />
    6566                <attribute name="Base-Revision" value="${workspace.version}" />
     
    139140            <manifest>
    140141                <attribute name="Implementation-Version" value="${full.version}" />
     142                <attribute name="Built-By" value="${build.built-by}" />
    141143                <attribute name="Build-Date" value="${build.timestamp}" />
    142144                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java

    rf43b0be r2b81cee  
    1414import java.net.Socket;
    1515import java.net.SocketException;
     16import java.net.URI;
     17import java.net.URISyntaxException;
    1618import java.util.ArrayList;
    1719import java.util.Date;
     
    3739import net.i2p.data.Destination;
    3840import net.i2p.data.Hash;
     41import net.i2p.i2ptunnel.localServer.LocalHTTPServer;
    3942import net.i2p.util.EventDispatcher;
    40 import net.i2p.util.FileUtil;
    4143import net.i2p.util.Log;
    4244import net.i2p.util.PortMapper;
     
    6264 * resolve correctly, cookies won't work, etc.
    6365 *
     66 * Note that http://$b64key/... and http://$b64key.i2p/... are NOT supported, as
     67 * a b64 key may contain '=' and '~', both of which are illegal host name characters.
     68 * Rewrite as http://i2p/$b64key/...
     69 *
    6470 * If the $site resolves with the I2P naming service, then it is directed towards
    6571 * that eepsite, otherwise it is directed towards this client's outproxy (typically
     
    103109         "wrong BASE64 I2P Destination or the link you are following is "+
    104110         "bad. The host (or the WWW proxy, if you're using one) could also "+
    105      "be temporarily offline.  You may want to <b>retry</b>.  "+
     111         "be temporarily offline.  You may want to <b>retry</b>.  "+
    106112         "Could not find the following Destination:<BR><BR><div>")
    107113        .getBytes();
     
    310316    }
    311317
    312     private static final String LOCAL_SERVER = "proxy.i2p";
     318    private static final String HELPER_PARAM = "i2paddresshelper";
     319    public static final String LOCAL_SERVER = "proxy.i2p";
    313320    private static final boolean DEFAULT_GZIP = true;
    314321    /** all default to false */
     
    322329        InputStream in = null;
    323330        OutputStream out = null;
     331
     332        /**
     333         * The URL after fixup, always starting with http://
     334         */
    324335        String targetRequest = null;
     336
    325337        boolean usingWWWProxy = false;
    326338        boolean usingInternalServer = false;
     339        String internalPath = null;
     340        String internalRawQuery = null;
    327341        String currentProxy = null;
    328342        long requestId = ++__requestId;
     343
    329344        try {
    330345            out = s.getOutputStream();
     
    352367                        _log.debug(getPrefix(requestId) + "First line [" + line + "]");
    353368
    354                     int pos = line.indexOf(" ");
    355                     if (pos == -1) break;
    356                     method = line.substring(0, pos);
    357                     // TODO use Java URL class to make all this simpler and more robust
    358                     // That will also fix IPV6 [a:b:c]
    359                     String request = line.substring(pos + 1);
     369                    String[] params = line.split(" ", 3);
     370                    if (params.length != 3)
     371                        break;
     372                    String request = params[1];
     373
     374                    // various obscure fixups
    360375                    if (request.startsWith("/") && getTunnel().getClientOptions().getProperty("i2ptunnel.noproxy") != null) {
    361376                        // what is this for ???
    362377                        request = "http://i2p" + request;
    363378                    } else if (request.startsWith("/eepproxy/")) {
    364                         // /eepproxy/foo.i2p/bar/baz.html HTTP/1.0
     379                        // Deprecated
     380                        // /eepproxy/foo.i2p/bar/baz.html
    365381                        String subRequest = request.substring("/eepproxy/".length());
    366                         int protopos = subRequest.indexOf(" ");
    367                         String uri = subRequest.substring(0, protopos);
    368                         if (uri.indexOf("/") == -1) {
    369                                 uri = uri + "/";
     382                        if (subRequest.indexOf("/") == -1)
     383                                subRequest += "/";
     384                        request = "http://" + subRequest;
     385                 /****
     386                    } else if (request.toLowerCase(Locale.US).startsWith("http://i2p/")) {
     387                        // http://i2p/b64key/bar/baz.html
     388                        // we can't do this now by setting the URI host to the b64key, as
     389                        // it probably contains '=' and '~' which are illegal,
     390                        // and a host may not include escaped octets
     391                        // This will get undone below.
     392                        String subRequest = request.substring("http://i2p/".length());
     393                        if (subRequest.indexOf("/") == -1)
     394                                subRequest += "/";
     395                         "http://" + "b64key/bar/baz.html"
     396                        request = "http://" + subRequest;
     397                    } else if (request.toLowerCase(Locale.US).startsWith("http://")) {
     398                        // Unsupported
     399                        // http://$b64key/...
     400                        // This probably used to work, rewrite it so that
     401                        // we can create a URI without illegal characters
     402                        // This will get undone below.
     403                        String  oldPath = request.substring(7);
     404                        int slash = oldPath.indexOf("/");
     405                        if (slash < 0)
     406                            slash = oldPath.length();
     407                        if (slash >= 516 && !oldPath.substring(0, slash).contains("."))
     408                            request = "http://i2p/" + oldPath;
     409                   ****/
     410                    }
     411
     412                    // Now use the Java URI parser
     413                    // This will be the incoming URI but will then get modified
     414                    // to be the outgoing URI (with http:// if going to outproxy, otherwise without)
     415                    URI requestURI;
     416                    try {
     417                        requestURI = new URI(request);
     418                        if (requestURI.getRawUserInfo() != null || requestURI.getRawFragment() != null) {
     419                            // these should never be sent to the proxy in the request line
     420                            if (_log.shouldLog(Log.WARN))
     421                                _log.warn(getPrefix(requestId) + "Removing userinfo or fragment [" + request + "]");
     422                            requestURI = changeURI(requestURI, null, 0, null);
    370423                        }
    371                         // "http://" + "foo.i2p/bar/baz.html" + " HTTP/1.0"
    372                         request = "http://" + uri + subRequest.substring(protopos);
    373                     } else if (request.toLowerCase(Locale.US).startsWith("http://i2p/")) {
    374                         // http://i2p/b64key/bar/baz.html HTTP/1.0
    375                         String subRequest = request.substring("http://i2p/".length());
    376                         int protopos = subRequest.indexOf(" ");
    377                         String uri = subRequest.substring(0, protopos);
    378                         if (uri.indexOf("/") == -1) {
    379                                 uri = uri + "/";
     424                        if (requestURI.getPath() == null || requestURI.getPath().length() <= 0) {
     425                            // Add a path
     426                            if (_log.shouldLog(Log.WARN))
     427                                _log.warn(getPrefix(requestId) + "Adding / path to [" + request + "]");
     428                            requestURI = changeURI(requestURI, null, 0, "/");
    380429                        }
    381                         // "http://" + "b64key/bar/baz.html" + " HTTP/1.0"
    382                         request = "http://" + uri + subRequest.substring(protopos);
     430                    } catch (URISyntaxException use) {
     431                        if (_log.shouldLog(Log.WARN))
     432                            _log.warn(getPrefix(requestId) + "Bad request [" + request + "]", use);
     433                        break;
    383434                    }
    384 
    385                     pos = request.indexOf("//");
    386                     if (pos == -1) {
     435                    method = params[0];
     436                    String protocolVersion = params[2];
     437
     438                    protocol = requestURI.getScheme();
     439                    host = requestURI.getHost();
     440                    if (protocol == null || host == null) {
     441                        _log.warn("Null protocol or host: " + request);
    387442                        method = null;
    388443                        break;
    389444                    }
    390                     protocol = request.substring(0, pos + 2);
    391                     request = request.substring(pos + 2);
    392 
    393                     // "foo.i2p/bar/baz HTTP/1.1", with any i2paddresshelper parameter removed
    394                     targetRequest = request;
    395 
    396                     // pos is the start of the path
    397                     pos = request.indexOf("/");
    398                     if (pos == -1) {
    399                         //pos = request.length();
    400                         method = null;
    401                         break;
    402                     }
    403                     host = request.substring(0, pos);
    404 
    405                     // parse port
    406                     int posPort = host.indexOf(":");
    407                     int port = 80;
    408                     if(posPort != -1) {
    409                         String[] parts = host.split(":");
    410                         try {
    411                         host = parts[0];
    412                         } catch (ArrayIndexOutOfBoundsException ex) {
    413                         if (out != null) {
    414                             out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
    415                             writeFooter(out);
    416                         }
    417                         s.close();
    418                         return;
    419 
    420                         }
    421                         try {
    422                             port = Integer.parseInt(parts[1]);
    423                         } catch(Exception exc) {
    424                             // TODO: log this
    425                         }
    426                     }
     445
     446                    int port = requestURI.getPort();
    427447
    428448                    // Go through the various types of host names, set
     
    434454                    // and it is removed from the request line.
    435455
    436                     if (host.length() >= 516 && host.indexOf(".") < 0) {
    437                         // http://b64key/bar/baz.html
    438                         destination = host;
    439                         host = getHostName(destination);
    440                         line = method + ' ' + request.substring(pos);
    441                     } else if (host.toLowerCase(Locale.US).equals(LOCAL_SERVER)) {
     456                    String hostLowerCase = host.toLowerCase(Locale.US);
     457                    if (hostLowerCase.equals(LOCAL_SERVER)) {
    442458                        // so we don't do any naming service lookups
    443459                        destination = host;
    444460                        usingInternalServer = true;
    445                     } else if (host.toLowerCase(Locale.US).endsWith(".i2p")) {
     461                        internalPath = requestURI.getPath();
     462                        internalRawQuery = requestURI.getRawQuery();
     463                    } else if (hostLowerCase.equals("i2p")) {
     464                        // pull the b64 dest out of the first path element
     465                        String oldPath = requestURI.getPath().substring(1);
     466                        int slash = oldPath.indexOf("/");
     467                        if (slash < 0) {
     468                            slash = oldPath.length();
     469                            oldPath += "/";
     470                        }
     471                        String dest = oldPath.substring(0, slash);
     472                        if (slash >= 516 && !dest.contains(".")) {
     473                            // possible alternative:
     474                            // redirect to b32
     475                            destination = dest;
     476                            host = getHostName(destination);
     477                            targetRequest = requestURI.toASCIIString();
     478                            String newURI = oldPath.substring(slash);
     479                            String query = requestURI.getRawQuery();
     480                            if (query != null)
     481                                newURI += '?' + query;
     482                            try {
     483                                requestURI = new URI(newURI);
     484                            } catch (URISyntaxException use) {
     485                                // shouldnt happen
     486                                _log.warn(request, use);
     487                                method = null;
     488                                break;
     489                            }
     490                        } else {
     491                            _log.warn("Bad http://i2p/b64dest " + request);
     492                            host = null;
     493                            break;
     494                        }
     495                    } else if (hostLowerCase.endsWith(".i2p")) {
    446496                        // Destination gets the host name
    447497                        destination = host;
     
    449499                        host = getHostName(destination);
    450500
    451                         int pos2;
    452                         if ((pos2 = request.indexOf("?")) != -1) {
    453                             // Try to find an address helper in the fragments
    454                             // and split the request into it's component parts for rebuilding later
     501                        if (requestURI.getPort() >= 0) {
     502                            // TODO support I2P ports someday
     503                            //if (port >= 0)
     504                            //    host = host + ':' + port;
     505                            if (_log.shouldLog(Log.WARN))
     506                                _log.warn(getPrefix(requestId) + "Removing port from [" + request + "]");
     507                            try {
     508                                requestURI = changeURI(requestURI, null, -1, null);
     509                            } catch (URISyntaxException use) {
     510                                _log.warn(request, use);
     511                                method = null;
     512                                break;
     513                            }
     514                        }
     515
     516                        String query = requestURI.getRawQuery();
     517                        if (query != null) {
    455518                            boolean ahelperConflict = false;
    456519
    457                             String fragments = request.substring(pos2 + 1);
    458                             String uriPath = request.substring(0, pos2);
    459                             pos2 = fragments.indexOf(" ");
    460                             String protocolVersion = fragments.substring(pos2 + 1);
    461                             String urlEncoding = "";
    462                             fragments = fragments.substring(0, pos2);
    463                             String initialFragments = fragments;
    464                             // FIXME split on ';' also
    465                             fragments = fragments + "&";
    466                             String fragment;
    467                             while(fragments.length() > 0) {
    468                                 pos2 = fragments.indexOf("&");
    469                                 fragment = fragments.substring(0, pos2);
    470                                 fragments = fragments.substring(pos2 + 1);
    471 
    472                                 // Fragment looks like addresshelper key
    473                                 if (fragment.startsWith("i2paddresshelper=") &&
    474                                     !Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
    475                                     pos2 = fragment.indexOf("=");
    476                                     ahelperKey = fragment.substring(pos2 + 1);
    477                                     // Key contains data, lets not ignore it
    478                                     if (ahelperKey != null) {
    479                                         if(ahelperKey.endsWith(".i2p")) {
    480                                             // allow i2paddresshelper=<b32>.b32.i2p syntax.
    481                                             /*
    482                                               also i2paddresshelper=name.i2p for aliases
    483                                               i.e. on your eepsite put
    484                                               <a href="?i2paddresshelper=name.i2p">This is the name I want to be called.</a>
    485                                             */
    486                                             Destination dest = _context.namingService().lookup(ahelperKey);
    487                                             if(dest==null) {
    488                                                 if (_log.shouldLog(Log.WARN))
    489                                                     _log.warn(getPrefix(requestId) + "Could not find destination for "+ahelperKey);
    490                                                 byte[] header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND);
    491                                                 out.write(header);
    492                                                 out.write(("<p>" + _("This seems to be a bad destination:") + " " + ahelperKey + " " + _("i2paddresshelper cannot help you with a destination like that!") + "</p>").getBytes("UTF-8"));
    493                                                 writeFooter(out);
    494                                                 // XXX: should closeSocket(s) be in a finally block?
    495                                                 closeSocket(s);
    496                                                 return;
    497                                             }
    498                                             ahelperKey = dest.toBase64();
    499                                         }
    500 
    501                                         ahelperPresent = true;
    502                                         // ahelperKey will be validated later
    503                                         if (host == null || "i2p".equals(host)) {
    504                                             // Host lookup failed - resolvable only with addresshelper
    505                                             // Store in local HashMap unless there is conflict
    506                                             String old = addressHelpers.putIfAbsent(destination.toLowerCase(Locale.US), ahelperKey);
    507                                             ahelperNew = old == null;
    508                                             if ((!ahelperNew) && !old.equals(ahelperKey)) {
     520                            // Try to find an address helper in the query
     521                            String[] helperStrings = removeHelper(query);
     522                            if (helperStrings != null &&
     523                                !Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
     524                                query = helperStrings[0];
     525                                if (query.equals(""))
     526                                    query = null;
     527                                try {
     528                                    requestURI = replaceQuery(requestURI, query);
     529                                } catch (URISyntaxException use) {
     530                                    // shouldn't happen
     531                                    _log.warn(request, use);
     532                                    method = null;
     533                                    break;
     534                                }
     535                                ahelperKey = helperStrings[1];
     536                                // Key contains data, lets not ignore it
     537                                if (ahelperKey.length() > 0) {
     538                                    if(ahelperKey.endsWith(".i2p")) {
     539                                        // allow i2paddresshelper=<b32>.b32.i2p syntax.
     540                                        /*
     541                                          also i2paddresshelper=name.i2p for aliases
     542                                          i.e. on your eepsite put
     543                                          <a href="?i2paddresshelper=name.i2p">This is the name I want to be called.</a>
     544                                        */
     545                                        Destination dest = _context.namingService().lookup(ahelperKey);
     546                                        if(dest==null) {
     547                                            if (_log.shouldLog(Log.WARN))
     548                                                _log.warn(getPrefix(requestId) + "Could not find destination for "+ahelperKey);
     549                                            byte[] header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND);
     550                                            out.write(header);
     551                                            out.write(("<p>" + _("This seems to be a bad destination:") + " " + ahelperKey + " " + _("i2paddresshelper cannot help you with a destination like that!") + "</p>").getBytes("UTF-8"));
     552                                            writeFooter(out);
     553                                            // XXX: should closeSocket(s) be in a finally block?
     554                                            closeSocket(s);
     555                                            return;
     556                                        }
     557                                        ahelperKey = dest.toBase64();
     558                                    }
     559
     560                                    ahelperPresent = true;
     561                                    // ahelperKey will be validated later
     562                                    if (host == null || "i2p".equals(host)) {
     563                                        // Host lookup failed - resolvable only with addresshelper
     564                                        // Store in local HashMap unless there is conflict
     565                                        String old = addressHelpers.putIfAbsent(destination.toLowerCase(Locale.US), ahelperKey);
     566                                        ahelperNew = old == null;
     567                                        if ((!ahelperNew) && !old.equals(ahelperKey)) {
     568                                            // Conflict: handle when URL reconstruction done
     569                                            ahelperConflict = true;
     570                                            if (_log.shouldLog(Log.WARN))
     571                                                _log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination +
     572                                                          "], trusted key [" + old + "], specified key [" + ahelperKey + "].");
     573                                        }
     574                                    } else {
     575                                        // If the host is resolvable from database, verify addresshelper key
     576                                        // Silently bypass correct keys, otherwise alert
     577                                        Destination hostDest = _context.namingService().lookup(destination);
     578                                        if (hostDest != null) {
     579                                            String destB64 = hostDest.toBase64();
     580                                            if (destB64 != null && !destB64.equals(ahelperKey)) {
    509581                                                // Conflict: handle when URL reconstruction done
    510582                                                ahelperConflict = true;
    511583                                                if (_log.shouldLog(Log.WARN))
    512584                                                    _log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination +
    513                                                               "], trusted key [" + old + "], specified key [" + ahelperKey + "].");
    514                                             }
    515                                         } else {
    516                                             // If the host is resolvable from database, verify addresshelper key
    517                                             // Silently bypass correct keys, otherwise alert
    518                                             Destination hostDest = _context.namingService().lookup(destination);
    519                                             if (hostDest != null) {
    520                                                 String destB64 = hostDest.toBase64();
    521                                                 if (destB64 != null && !destB64.equals(ahelperKey)) {
    522                                                     // Conflict: handle when URL reconstruction done
    523                                                     ahelperConflict = true;
    524                                                     if (_log.shouldLog(Log.WARN))
    525                                                         _log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination +
    526                                                                   "], trusted key [" + destB64 + "], specified key [" + ahelperKey + "].");
    527                                                    
    528                                                 }
     585                                                              "], trusted key [" + destB64 + "], specified key [" + ahelperKey + "].");
     586                                               
    529587                                            }
    530588                                        }
    531                                     } // ahelperKey
    532                                 } else {
    533                                     // Other fragments, just pass along
    534                                     // Append each fragment to urlEncoding
    535                                     if ("".equals(urlEncoding)) {
    536                                         urlEncoding = "?" + fragment;
    537                                     } else {
    538                                         urlEncoding = urlEncoding + "&" + fragment;
    539589                                    }
    540                                 }
    541                             }
    542                             // Reconstruct the request minus the i2paddresshelper GET var
    543                             request = uriPath + urlEncoding + " " + protocolVersion;
    544                             targetRequest = request;
     590                                } // ahelperKey
     591                            } // helperstrings
    545592
    546593                            // Did addresshelper key conflict?
     
    554601                                        writeErrorMessage(header, out, targetRequest, false, destination, null);
    555602                                    } else {
    556                                         String trustedURL = protocol + uriPath + urlEncoding;
    557                                         // Fixme - any path is lost
    558                                         String conflictURL = protocol + alias + '/' + urlEncoding;
     603                                        String trustedURL = requestURI.toASCIIString();
     604                                        URI conflictURI;
     605                                        try {
     606                                            conflictURI = changeURI(requestURI, alias, 0, null);
     607                                        } catch (URISyntaxException use) {
     608                                            // shouldn't happen
     609                                            _log.warn(request, use);
     610                                            method = null;
     611                                            break;
     612                                        }
     613                                        String conflictURL = conflictURI.toASCIIString();
    559614                                        byte[] header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT);
    560615                                        out.write(header);
     
    573628                            host = getHostName(addressHelper);
    574629
    575                         line = method + " " + request.substring(pos);
     630                        // now strip everything but path and query from URI
     631                        targetRequest = requestURI.toASCIIString();
     632                        String newURI = requestURI.getRawPath();
     633                        if (query != null)
     634                            newURI += '?' + query;
     635                        try {
     636                            requestURI = new URI(newURI);
     637                        } catch (URISyntaxException use) {
     638                            // shouldnt happen
     639                            _log.warn(request, use);
     640                            method = null;
     641                            break;
     642                        }
     643
    576644                        // end of (host endsWith(".i2p"))
    577645
    578                     } else if (host.toLowerCase(Locale.US).equals("localhost") || host.equals("127.0.0.1") ||
    579                                host.startsWith("192.168.")) {
     646                    } else if (hostLowerCase.equals("localhost") || host.equals("127.0.0.1") ||
     647                               host.startsWith("192.168.") || host.equals("[::1]")) {
    580648                        // if somebody is trying to get to 192.168.example.com, oh well
    581649                        if (out != null) {
     
    585653                        s.close();
    586654                        return;
    587                     } else if (host.indexOf(".") != -1) {
    588                         // rebuild host
    589                         host = host + ":" + port;
     655                    } else if (host.contains(".") || host.startsWith("[")) {
     656                        if (port >= 0)
     657                            host = host + ':' + port;
    590658                        // The request must be forwarded to a WWW proxy
    591659                        if (_log.shouldLog(Log.DEBUG))
     
    607675                        destination = currentProxy;
    608676                        usingWWWProxy = true;
     677                        targetRequest = requestURI.toASCIIString();
    609678                        if (_log.shouldLog(Log.DEBUG))
    610                             _log.debug(getPrefix(requestId) + "Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!");
     679                            _log.debug(getPrefix(requestId) +  " [" + host + "]: wwwProxy!");
    611680                    } else {
    612681                        // what is left for here? a hostname with no dots, and != "i2p"
    613682                        // and not a destination ???
    614683                        // Perhaps something in privatehosts.txt ...
    615                         request = request.substring(pos + 1);
    616                         pos = request.indexOf("/");
    617                         if (pos < 0) {
    618                             l.log("Invalid request url [" + request + "]");
    619                             if (out != null) {
    620                                 out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
    621                                 writeFooter(out);
    622                             }
    623                             s.close();
    624                             return;
    625                         }
    626                         destination = request.substring(0, pos);
    627                         host = getHostName(destination);
    628                         line = method + " " + request.substring(pos);
    629                     }   // end host name processing
    630 
    631                     if (port != 80 && !usingWWWProxy) {
     684                        // Rather than look it up, just bail out.
     685                        if (_log.shouldLog(Log.WARN))
     686                            _log.warn("NODOTS, NOI2P: " + request);
    632687                        if (out != null) {
    633688                            out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
     
    636691                        s.close();
    637692                        return;
    638                     }
     693                    }   // end host name processing
    639694
    640695                    boolean isValid = usingWWWProxy || usingInternalServer || isSupportedAddress(host, protocol);
     
    646701                    }
    647702
    648                     // don't do this, it forces yet another hostname lookup,
    649                     // and in all cases host was already set above
    650                     //if ((!usingWWWProxy) && (!usingInternalServer)) {
    651                     //    String oldhost = host;
    652                     //    host = getHostName(destination); // hide original host
    653                     //    if (_log.shouldLog(Log.INFO))
    654                     //        _log.info(getPrefix(requestId) + " oldhost " + oldhost + " newhost " + host + " dest " + destination);
    655                     //}
     703                    line = method + ' ' + requestURI.toASCIIString() + ' ' + protocolVersion;
    656704
    657705                    if (_log.shouldLog(Log.DEBUG)) {
    658                         _log.debug(getPrefix(requestId) + "METHOD: \"" + method + "\"");
    659                         _log.debug(getPrefix(requestId) + "PROTOC: \"" + protocol + "\"");
     706                        _log.debug(getPrefix(requestId) + "NEWREQ: \"" + line + "\"");
    660707                        _log.debug(getPrefix(requestId) + "HOST  : \"" + host + "\"");
    661708                        _log.debug(getPrefix(requestId) + "DEST  : \"" + destination + "\"");
     
    764811                //l.log("No HTTP method found in the request.");
    765812                if (out != null) {
    766                     if (protocol != null && "http://".equals(protocol.toLowerCase(Locale.US)))
     813                    if (protocol != null && "http".equals(protocol.toLowerCase(Locale.US)))
    767814                        out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
    768815                    else
     
    795842            if (usingInternalServer) {
    796843                // disable the add form if address helper is disabled
    797                 if (targetRequest.startsWith(LOCAL_SERVER + "/add?") &&
     844                if (internalPath.equals("/add") &&
    798845                    Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
    799846                    out.write(ERR_HELPER_DISABLED);
    800847                } else {
    801                     serveLocalFile(out, method, targetRequest, _proxyNonce);
     848                    LocalHTTPServer.serveLocalFile(out, method, internalPath, internalRawQuery, _proxyNonce);
    802849                }
    803850                s.close();
     
    813860            if (addressHelper != null) {
    814861                clientDest = _context.namingService().lookup(addressHelper);
    815                 // remove bad entries
    816                 if (clientDest == null)
     862                if (clientDest == null) {
     863                    // remove bad entries
    817864                    addressHelpers.remove(destination.toLowerCase(Locale.US));
     865                    if (_log.shouldLog(Log.WARN))
     866                        _log.warn(getPrefix(requestId) + "Could not find destination for " + addressHelper);
     867                    byte[] header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND);
     868                    writeErrorMessage(header, out, targetRequest, false, destination, null);
     869                    s.close();
     870                    return;
     871                }
    818872            } else if ("i2p".equals(host)) {
    819873                clientDest = null;
     
    866920                (userAgent == null || !userAgent.startsWith("Wget")) &&
    867921                !Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
    868                 writeHelperSaveForm(out, destination, ahelperKey, protocol + targetRequest);
     922                writeHelperSaveForm(out, destination, ahelperKey, targetRequest);
    869923                s.close();
    870924                return;
     
    876930            // Syndie can't handle a redirect of a POST
    877931            if (ahelperPresent && !"POST".equals(method)) {
    878                 String uri = protocol + targetRequest;
    879                 int spc = uri.indexOf(" ");
    880                 if (spc >= 0)
    881                     uri = uri.substring(0, spc);
     932                String uri = targetRequest;
    882933                if (_log.shouldLog(Log.DEBUG))
    883934                    _log.debug("Auto redirecting to " + uri);
     
    929980        if (out == null)
    930981            return;
    931         // strip HTTP/1.1
    932         int protopos = targetRequest.indexOf(" ");
    933         if (protopos >= 0)
    934             targetRequest = targetRequest.substring(0, protopos);
    935982        byte[] header = getErrorPage("ahelper-new", ERR_AHELPER_NEW);
    936983        out.write(header);
     
    940987                   ahelperKey + "</textarea></td></tr></table>\n" +
    941988                   "<hr><div class=\"formaction\">"+
     989                   // FIXME if there is a query remaining it is lost
    942990                   "<form method=\"GET\" action=\"" + targetRequest + "\">" +
    943991                   "<button type=\"submit\" class=\"go\">" + _("Continue to {0} without saving", destination) + "</button>" +
     
    10471095    }
    10481096
    1049     private static void writeFooter(OutputStream out) throws IOException {
     1097    /**
     1098     *  Public only for LocalHTTPServer, not for general use
     1099     */
     1100    public static void writeFooter(OutputStream out) throws IOException {
    10501101        // the css is hiding this div for now, but we'll keep it here anyway
    10511102        out.write("<div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br>Generated on: ".getBytes());
     
    10921143            out.write(errMessage);
    10931144            if (targetRequest != null) {
    1094                 int protopos = targetRequest.indexOf(" ");
    1095                 String uri;
    1096                 if (protopos >= 0)
    1097                     uri = targetRequest.substring(0, protopos);
    1098                 else
    1099                     uri = targetRequest;
    1100                 out.write("<a href=\"http://".getBytes());
     1145                String uri = targetRequest;
     1146                out.write("<a href=\"".getBytes());
    11011147                out.write(uri.getBytes());
    1102                 out.write("\">http://".getBytes());
     1148                out.write("\">".getBytes());
    11031149                out.write(uri.getBytes());
    11041150                out.write("</a>".getBytes());
     
    11941240        }
    11951241      ****/
    1196         return protocol.toLowerCase(Locale.US).equals("http://");
    1197     }
    1198 
    1199     private final static byte[] ERR_404 =
    1200         ("HTTP/1.1 404 Not Found\r\n"+
    1201          "Content-Type: text/plain\r\n"+
    1202          "\r\n"+
    1203          "HTTP Proxy local file not found")
    1204         .getBytes();
    1205 
    1206     private final static byte[] ERR_ADD =
    1207         ("HTTP/1.1 409 Bad\r\n"+
    1208          "Content-Type: text/plain\r\n"+
    1209          "\r\n"+
    1210          "Add to addressbook failed - bad parameters")
    1211         .getBytes();
     1242        return protocol.toLowerCase(Locale.US).equals("http");
     1243    }
    12121244
    12131245    private final static byte[] ERR_HELPER_DISABLED =
     
    12191251
    12201252    /**
    1221      *  Very simple web server.
     1253     *  Change various parts of the URI.
     1254     *  String parameters are all non-encoded.
    12221255     *
    1223      *  Serve local files in the docs/ directory, for CSS and images in
    1224      *  error pages, using the reserved address proxy.i2p
    1225      *  (similar to p.p in privoxy).
    1226      *  This solves the problems with including links to the router console,
    1227      *  as assuming the router console is at 127.0.0.1 leads to broken
    1228      *  links if it isn't.
     1256     *  Scheme always preserved.
     1257     *  Userinfo always cleared.
     1258     *  Host changed if non-null.
     1259     *  Port changed if non-zero.
     1260     *  Path changed if non-null.
     1261     *  Query always preserved.
     1262     *  Fragment always cleared.
    12291263     *
    1230      *  Ignore all request headers (If-Modified-Since, etc.)
     1264     *  @since 0.9
     1265     */
     1266    private static URI changeURI(URI uri, String host, int port, String path) throws URISyntaxException {
     1267        return new URI(uri.getScheme(),
     1268                       null,
     1269                       host != null ? host : uri.getHost(),
     1270                       port != 0 ? port : uri.getPort(),
     1271                       path != null ? path : uri.getPath(),
     1272                       // FIXME this breaks encoded =, &
     1273                       uri.getQuery(),
     1274                       null);
     1275    }
     1276
     1277    /**
     1278     *  Replace query in the URI.
     1279     *  Userinfo cleared if uri contained a query.
     1280     *  Fragment cleared if uri contained a query.
    12311281     *
    1232      *  There is basic protection here -
    1233      *  FileUtil.readFile() prevents traversal above the base directory -
    1234      *  but inproxy/gateway ops would be wise to block proxy.i2p to prevent
    1235      *  exposing the docs/ directory or perhaps other issues through
    1236      *  uncaught vulnerabilities.
    1237      *  Restrict to the /themes/ directory for now.
     1282     *  @param query an ENCODED query, removed if null
     1283     *  @since 0.9
     1284     */
     1285    private static URI replaceQuery(URI uri, String query) throws URISyntaxException {
     1286        URI rv = uri;
     1287        if (rv.getRawQuery() != null) {
     1288            rv = new URI(rv.getScheme(),
     1289                       null,
     1290                       uri.getHost(),
     1291                       uri.getPort(),
     1292                       uri.getPath(),
     1293                       null,
     1294                       null);
     1295        }
     1296        if (query != null) {
     1297            String newURI = rv.toASCIIString() + '?' + query;
     1298            rv = new URI(newURI);
     1299        }
     1300        return rv;
     1301    }
     1302
     1303    /**
     1304     *  Remove the address helper from an encoded query.
    12381305     *
    1239      *  @param targetRequest "proxy.i2p/themes/foo.png HTTP/1.1"
    1240      */
    1241     private static void serveLocalFile(OutputStream out, String method, String targetRequest, String proxyNonce) {
    1242         //System.err.println("targetRequest: \"" + targetRequest + "\"");
    1243         // a home page message for the curious...
    1244         if (targetRequest.startsWith(LOCAL_SERVER + "/ ")) {
    1245             try {
    1246                 out.write(("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nCache-Control: max-age=86400\r\n\r\nI2P HTTP proxy OK").getBytes());
    1247                 out.flush();
    1248             } catch (IOException ioe) {}
    1249             return;
    1250         }
    1251         if ((method.equals("GET") || method.equals("HEAD")) &&
    1252             targetRequest.startsWith(LOCAL_SERVER + "/themes/") &&
    1253             !targetRequest.contains("..")) {
    1254             int space = targetRequest.indexOf(' ');
    1255             String filename = null;
    1256             try {
    1257                 filename = targetRequest.substring(LOCAL_SERVER.length() + 8, space); // "/themes/".length
    1258             } catch (IndexOutOfBoundsException ioobe) {
    1259                  return;
     1306     *  @param query an ENCODED query, removed if null
     1307     *  @return rv[0] is ENCODED query with helper removed, non-null but possibly empty;
     1308     *          rv[1] is DECODED helper value, non-null but possibly empty;
     1309     *          rv null if no helper present
     1310     *  @since 0.9
     1311     */
     1312    private static String[] removeHelper(String query) {
     1313        int keystart = 0;
     1314        int valstart = -1;
     1315        String key = null;
     1316        for (int i = 0; i <= query.length(); i++) {
     1317            char c = i < query.length() ? query.charAt(i) : '&';
     1318            if (c == ';' || c == '&') {
     1319                // end of key or value
     1320                if (valstart < 0)
     1321                    key = query.substring(keystart, i);
     1322                String decodedKey = LocalHTTPServer.decode(key);
     1323                if (decodedKey.equals(HELPER_PARAM)) {
     1324                    String newQuery = keystart > 0 ? query.substring(0, keystart - 1) : "";
     1325                    if (i < query.length() - 1) {
     1326                        if (keystart > 0)
     1327                            newQuery += query.substring(i);
     1328                        else
     1329                            newQuery += query.substring(i + 1);
     1330                    }
     1331                    String value = valstart >= 0 ? query.substring(valstart, i) : "";
     1332                    String helperValue = LocalHTTPServer.decode(value);
     1333                    return new String[] { newQuery, helperValue };
     1334                }
     1335                keystart = i + 1;
     1336                valstart = -1;
     1337            } else if (c == '=') {
     1338                // end of key
     1339                key = query.substring(keystart, i);
     1340                valstart = i + 1;
    12601341            }
    1261             // theme hack
    1262             if (filename.startsWith("console/default/"))
    1263                 filename = filename.replaceFirst("default", I2PAppContext.getGlobalContext().getProperty("routerconsole.theme", "light"));
    1264             File themesDir = new File(_errorDir, "themes");
    1265             File file = new File(themesDir, filename);
    1266             if (file.exists() && !file.isDirectory()) {
    1267                 String type;
    1268                 if (filename.endsWith(".css"))
    1269                     type = "text/css";
    1270                 else if (filename.endsWith(".ico"))
    1271                     type = "image/x-icon";
    1272                 else if (filename.endsWith(".png"))
    1273                     type = "image/png";
    1274                 else if (filename.endsWith(".jpg"))
    1275                     type = "image/jpeg";
    1276                 else type = "text/html";
    1277                 try {
    1278                     out.write("HTTP/1.1 200 OK\r\nContent-Type: ".getBytes());
    1279                     out.write(type.getBytes());
    1280                     out.write("\r\nCache-Control: max-age=86400\r\n\r\n".getBytes());
    1281                     FileUtil.readFile(filename, themesDir.getAbsolutePath(), out);
    1282                 } catch (IOException ioe) {}
    1283                 return;
    1284             }
    1285         }
    1286 
    1287         // Add to addressbook (form submit)
    1288         // Parameters are url, host, dest, nonce, and master | router | private.
    1289         // Do the add and redirect.
    1290         if (targetRequest.startsWith(LOCAL_SERVER + "/add?")) {
    1291             int spc = targetRequest.indexOf(' ');
    1292             String query = targetRequest.substring(LOCAL_SERVER.length() + 5, spc);   // "/add?".length()
    1293             Map<String, String> opts = new HashMap(8);
    1294             StringTokenizer tok = new StringTokenizer(query, "=&;");
    1295             while (tok.hasMoreTokens()) {
    1296                 String k = tok.nextToken();
    1297                 if (!tok.hasMoreTokens())
    1298                     break;
    1299                 String v = tok.nextToken();
    1300                 opts.put(decode(k), decode(v));
    1301             }
    1302 
    1303             String url = opts.get("url");
    1304             String host = opts.get("host");
    1305             String b64Dest = opts.get("dest");
    1306             String nonce = opts.get("nonce");
    1307             String book = "privatehosts.txt";
    1308             if (opts.get("master") != null)
    1309                 book = "userhosts.txt";
    1310             else if (opts.get("router") != null)
    1311                 book = "hosts.txt";
    1312             Destination dest = null;
    1313             if (b64Dest != null) {
    1314                 try {
    1315                     dest = new Destination(b64Dest);
    1316                 } catch (DataFormatException dfe) {
    1317                     System.err.println("Bad dest to save?" + b64Dest);
    1318                 }
    1319             }
    1320             //System.err.println("url          : \"" + url           + "\"");
    1321             //System.err.println("host         : \"" + host          + "\"");
    1322             //System.err.println("b64dest      : \"" + b64Dest       + "\"");
    1323             //System.err.println("book         : \"" + book          + "\"");
    1324             //System.err.println("nonce        : \"" + nonce         + "\"");
    1325             if (proxyNonce.equals(nonce) && url != null && host != null && dest != null) {
    1326                 try {
    1327                     NamingService ns = I2PAppContext.getGlobalContext().namingService();
    1328                     Properties nsOptions = new Properties();
    1329                     nsOptions.setProperty("list", book);
    1330                     nsOptions.setProperty("s", _("Added via address helper"));
    1331                     boolean success = ns.put(host, dest, nsOptions);
    1332                     writeRedirectPage(out, success, host, book, url);
    1333                     return;
    1334                 } catch (IOException ioe) {}
    1335             }
    1336             try {
    1337                 out.write(ERR_ADD);
    1338                 out.flush();
    1339             } catch (IOException ioe) {}
    1340             return;
    1341         }
    1342         try {
    1343             out.write(ERR_404);
    1344             out.flush();
    1345         } catch (IOException ioe) {}
    1346     }
    1347 
    1348     /** @since 0.8.7 */
    1349     private static void writeRedirectPage(OutputStream out, boolean success, String host, String book, String url) throws IOException {
    1350         out.write(("HTTP/1.1 200 OK\r\n"+
    1351                   "Content-Type: text/html; charset=UTF-8\r\n"+
    1352                   "\r\n"+
    1353                   "<html><head>"+
    1354                   "<title>" + _("Redirecting to {0}", host) + "</title>\n" +
    1355                   "<link rel=\"shortcut icon\" href=\"http://proxy.i2p/themes/console/images/favicon.ico\" >\n" +
    1356                   "<link href=\"http://proxy.i2p/themes/console/default/console.css\" rel=\"stylesheet\" type=\"text/css\" >\n" +
    1357                   "<meta http-equiv=\"Refresh\" content=\"1; url=" + url + "\">\n" +
    1358                   "</head><body>\n" +
    1359                   "<div class=logo>\n" +
    1360                   "<a href=\"http://127.0.0.1:7657/\" title=\"" + _("Router Console") + "\"><img src=\"http://proxy.i2p/themes/console/images/i2plogo.png\" alt=\"I2P Router Console\" border=\"0\"></a><hr>\n" +
    1361                   "<a href=\"http://127.0.0.1:7657/config\">" + _("Configuration") + "</a> <a href=\"http://127.0.0.1:7657/help.jsp\">" + _("Help") + "</a> <a href=\"http://127.0.0.1:7657/susidns/index\">" + _("Addressbook") + "</a>\n" +
    1362                   "</div>" +
    1363                   "<div class=warning id=warning>\n" +
    1364                   "<h3>" +
    1365                   (success ?
    1366                            _("Saved {0} to the {1} addressbook, redirecting now.", host, book) :
    1367                            _("Failed to save {0} to the {1} addressbook, redirecting now.", host, book)) +
    1368                   "</h3>\n<p><a href=\"" + url + "\">" +
    1369                   _("Click here if you are not redirected automatically.") +
    1370                   "</a></p></div>").getBytes("UTF-8"));
    1371         writeFooter(out);
    1372         out.flush();
    1373     }
    1374 
    1375     /**
    1376      *  Decode %xx encoding
    1377      *  @since 0.8.7
    1378      */
    1379     private static String decode(String s) {
    1380         if (!s.contains("%"))
    1381             return s;
    1382         StringBuilder buf = new StringBuilder(s.length());
    1383         for (int i = 0; i < s.length(); i++) {
    1384             char c = s.charAt(i);
    1385             if (c != '%') {
    1386                 buf.append(c);
    1387             } else {
    1388                 try {
    1389                     buf.append((char) Integer.parseInt(s.substring(++i, (++i) + 1), 16));
    1390                 } catch (IndexOutOfBoundsException ioobe) {
    1391                     break;
    1392                 } catch (NumberFormatException nfe) {
    1393                     break;
    1394                 }
    1395             }
    1396         }
    1397         return buf.toString();
    1398     }
    1399 
     1342        }
     1343        return null;
     1344    }
     1345
     1346/****
     1347    private static String[] tests = {
     1348        "", "foo", "foo=bar", "&", "&=&", "===", "&&",
     1349        "i2paddresshelper=foo",
     1350        "i2paddresshelpe=foo",
     1351        "2paddresshelper=foo",
     1352        "i2paddresshelper=%66oo",
     1353        "%692paddresshelper=foo",
     1354        "i2paddresshelper=foo&a=b",
     1355        "a=b&i2paddresshelper=foo",
     1356        "a=b&i2paddresshelper&c=d",
     1357        "a=b&i2paddresshelper=foo&c=d",
     1358        "a=b;i2paddresshelper=foo;c=d",
     1359        "a=b&i2paddresshelper=foo&c"
     1360    };
     1361
     1362    public static void main(String[] args) {
     1363        for (int i = 0; i < tests.length; i++) {
     1364            String[] s = removeHelper(tests[i]);
     1365            if (s != null)
     1366                System.out.println("Test \"" + tests[i] + "\" q=\"" + s[0] + "\" h=\"" + s[1] + "\"");
     1367            else
     1368                System.out.println("Test \"" + tests[i] + "\" no match");
     1369        }
     1370    }
     1371****/
     1372
     1373    /** */
    14001374    private static final String BUNDLE_NAME = "net.i2p.i2ptunnel.web.messages";
    14011375
  • apps/i2ptunnel/jsp/editClient.jsp

    rf43b0be r2b81cee  
    358358                <table border="0"><tr><!-- I give up -->
    359359                <td><input value="1" type="radio" id="startOnLoad" name="newDest" title="New Destination"
    360                      <%=(editBean.getNewDest(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />               
    361                 <td><%=intl._("Enable")%>
     360                     <%=(editBean.getNewDest(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" /></td>
     361                <td><%=intl._("Enable")%></td>
    362362                <td><input value="0" type="radio" id="startOnLoad" name="newDest" title="New Destination"
    363                      <%=(editBean.getNewDest(curTunnel) || editBean.getPersistentClientKey(curTunnel) ? "" : " checked=\"checked\"")%> class="tickbox" />               
    364                 <td><%=intl._("Disable")%>
     363                     <%=(editBean.getNewDest(curTunnel) || editBean.getPersistentClientKey(curTunnel) ? "" : " checked=\"checked\"")%> class="tickbox" /></td>
     364                <td><%=intl._("Disable")%></td></tr>
    365365                </table>
    366366            </div>
  • apps/i2ptunnel/jsp/wizard.jsp

    rf43b0be r2b81cee  
    11<%
    22    // NOTE: Do the header carefully so there is no whitespace before the <?xml... line
     3
     4    // http://www.crazysquirrel.com/computing/general/form-encoding.jspx
     5    if (request.getCharacterEncoding() == null)
     6        request.setCharacterEncoding("UTF-8");
    37
    48%><%@page pageEncoding="UTF-8"
  • apps/jetty/build.xml

    rf43b0be r2b81cee  
    183183        <jar destfile="./jettylib/jetty-i2p.jar" basedir="./build/obj" includes="**/*.class log4j.properties" >
    184184            <manifest>
     185                <attribute name="Built-By" value="${build.built-by}" />
    185186                <attribute name="Build-Date" value="${build.timestamp}" />
    186187                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/ministreaming/java/build.xml

    rf43b0be r2b81cee  
    5252            <manifest>
    5353                <attribute name="Implementation-Version" value="${full.version}" />
     54                <attribute name="Built-By" value="${build.built-by}" />
    5455                <attribute name="Build-Date" value="${build.timestamp}" />
    5556                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/routerconsole/java/build.xml

    rf43b0be r2b81cee  
    103103                <attribute name="Class-Path" value="i2p.jar router.jar jrobin.jar desktopgui.jar" />
    104104                <attribute name="Implementation-Version" value="${full.version}" />
     105                <attribute name="Built-By" value="${build.built-by}" />
    105106                <attribute name="Build-Date" value="${build.timestamp}" />
    106107                <attribute name="Base-Revision" value="${workspace.version}" />
     
    183184            <manifest>
    184185                <attribute name="Implementation-Version" value="${full.version}" />
     186                <attribute name="Built-By" value="${build.built-by}" />
    185187                <attribute name="Build-Date" value="${build.timestamp}" />
    186188                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java

    rf43b0be r2b81cee  
    5353            (mode == 1 && (!disabled) && (!ssl)) ||
    5454            (mode == 2 && (!disabled) && ssl))
    55             return "checked=\"true\"";
     55            return "checked=\"checked\"";
    5656        return "";
    5757    }
     
    6161        boolean enabled =  _context.getBooleanProperty(PROP_AUTH);
    6262        if (enabled)
    63             return "checked=\"true\"";
     63            return "checked=\"checked\"";
    6464        return "";
    6565    }
     
    254254        buf.append("</td><td align=\"center\" width=\"10%\"><input type=\"checkbox\" class=\"optbox\" name=\"").append(index).append(".enabled\" value=\"true\" ");
    255255        if (enabled) {
    256             buf.append("checked=\"true\" ");
     256            buf.append("checked=\"checked\" ");
    257257            if (ro)
    258                 buf.append("disabled=\"true\" ");
     258                buf.append("disabled=\"disabled\" ");
    259259        }
    260260        buf.append("></td><td align=\"center\" width=\"15%\">");
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigLoggingHelper.java

    rf43b0be r2b81cee  
    8181            buf.append("<option value=\"").append(l).append('\"');
    8282            if (l.equals(cur))
    83                 buf.append(" selected=\"true\"");
     83                buf.append(" selected=\"selected\"");
    8484            buf.append('>').append(_(l)).append("</option>\n");
    8585        }       
     
    122122        StringBuilder buf = new StringBuilder(65536);
    123123        buf.append("<select name=\"newlogclass\">\n" +
    124                    "<option value=\"\" selected=\"true\">")
     124                   "<option value=\"\" selected=\"selected\">")
    125125           .append(_("Select a class to add"))
    126126           .append("</option>\n");
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigNavHelper.java

    rf43b0be r2b81cee  
    1212    /** configX.jsp */
    1313    private static final String pages[] =
    14                                           {"", "net", "ui", "service", "update", "tunnels",
     14                                          {"", "net", "ui", "home", "service", "update", "tunnels",
    1515                                           "clients", "peer", "keyring", "logging", "stats",
    1616                                           "reseed", "advanced" };
    1717
    1818    private static final String titles[] =
    19                                           {_x("Bandwidth"), _x("Network"), _x("UI"), _x("Service"), _x("Update"), _x("Tunnels"),
     19                                          {_x("Bandwidth"), _x("Network"), _x("UI"), _x("Home Page"),
     20                                           _x("Service"), _x("Update"), _x("Tunnels"),
    2021                                           _x("Clients"), _x("Peers"), _x("Keyring"), _x("Logging"), _x("Stats"),
    2122                                           _x("Reseeding"), _x("Advanced") };
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java

    rf43b0be r2b81cee  
    2121    public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoport";
    2222    public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoip";
    23     private final static String CHECKED = " checked=\"true\" ";
    24     private final static String DISABLED = " disabled=\"true\" ";
     23    private final static String CHECKED = " checked=\"checked\" ";
     24    private final static String DISABLED = " disabled=\"disabled\" ";
    2525
    2626    public String getUdphostname() {
     
    251251            buf.append("<option style=\"text-align: right;\" value=\"").append(val).append("\" ");
    252252            if (pct == val) {
    253                 buf.append("selected=\"true\" ");
     253                buf.append("selected=\"selected\" ");
    254254                found = true;
    255255            }
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHelper.java

    rf43b0be r2b81cee  
    5757            (mode == 1 && (!disabled) && required) ||
    5858            (mode == 2 && disabled))
    59             return "checked=\"true\"";
     59            return "checked=\"checked\"";
    6060        return "";
    6161    }
     
    8383        boolean enabled =  _context.getBooleanProperty(prop);
    8484        if (enabled)
    85             return "checked=\"true\"";
     85            return "checked=\"checked\"";
    8686        return "";
    8787    }
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHelper.java

    rf43b0be r2b81cee  
    6060    }
    6161
    62     public ConfigStatsHelper() {}
    63    
     62    /**
     63     *  Just hide for everybody unless already set.
     64     *  To enable set advanced config stat.logFilters=foo before starting...
     65     *  it has to be set at startup anyway for logging to be enabled at all
     66     *  @since 0.9
     67     */
     68    public boolean shouldShowLog() {
     69        return !_filters.isEmpty();
     70    }
     71
    6472    public String getFilename() { return _context.statManager().getStatFile(); }
    6573   
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java

    rf43b0be r2b81cee  
    173173            buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Inbound options") + ":</td>\n" +
    174174                       "<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
    175             buf.append(".inboundOptions\" type=\"text\" size=\"32\" disabled=\"true\" " +
     175            buf.append(".inboundOptions\" type=\"text\" size=\"32\" disabled=\"disabled\" " +
    176176                       "value=\"");
    177177            for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
     
    186186            buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Outbound options") + ":</td>\n" +
    187187                       "<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
    188             buf.append(".outboundOptions\" type=\"text\" size=\"32\" disabled=\"true\" " +
     188            buf.append(".outboundOptions\" type=\"text\" size=\"32\" disabled=\"disabled\" " +
    189189                       "value=\"");
    190190            for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
     
    206206            buf.append("<option value=\"").append(i).append("\" ");
    207207            if (i == now)
    208                 buf.append("selected=\"true\" ");
     208                buf.append("selected=\"selected\" ");
    209209            buf.append(">").append(ngettext(DUMMY1 + name, DUMMY2 + name + 's', i));
    210210            buf.append("</option>\n");
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHelper.java

    rf43b0be r2b81cee  
    1515            buf.append("<input type=\"radio\" class=\"optbox\" name=\"theme\" ");
    1616            if (theme.equals(current))
    17                 buf.append("checked=\"true\" ");
     17                buf.append("checked=\"checked\" ");
    1818            buf.append("value=\"").append(theme).append("\">").append(_(theme)).append("<br>\n");
    1919        }
     
    7474            buf.append("<input type=\"radio\" class=\"optbox\" name=\"lang\" ");
    7575            if (langs[i].equals(current))
    76                 buf.append("checked=\"true\" ");
     76                buf.append("checked=\"checked\" ");
    7777            buf.append("value=\"").append(langs[i]).append("\">")
    7878               .append("<img height=\"11\" width=\"16\" alt=\"\" src=\"/flags.jsp?c=").append(flags[i]).append("\"> ")
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java

    rf43b0be r2b81cee  
    7676        String proxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY);
    7777        if (Boolean.valueOf(proxy).booleanValue())
    78             return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" checked=\"true\" >";
     78            return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" checked=\"checked\" >";
    7979        else
    8080            return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" >";
     
    8484        String foo = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_UNSIGNED);
    8585        if (Boolean.valueOf(foo).booleanValue())
    86             return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" checked=\"true\" >";
     86            return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" checked=\"checked\" >";
    8787        else
    8888            return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" >";
     
    107107            buf.append("<option value=\"").append(PERIODS[i]);
    108108            if (PERIODS[i] == ms)
    109                 buf.append("\" selected=\"true");
     109                buf.append("\" selected=\"selected");
    110110           
    111111            if (PERIODS[i] == -1)
     
    129129        buf.append("<option value=\"notify\"");
    130130        if ("notify".equals(policy) || _dontInstall)
    131             buf.append(" selected=\"true\"");
     131            buf.append(" selected=\"selected\"");
    132132        buf.append('>').append(_("Notify only")).append("</option>");
    133133
    134134        buf.append("<option value=\"download\"");
    135135        if (_dontInstall)
    136             buf.append(" disabled=\"true\"");
     136            buf.append(" disabled=\"disabled\"");
    137137        else if ("download".equals(policy))
    138             buf.append(" selected=\"true\"");
     138            buf.append(" selected=\"selected\"");
    139139        buf.append('>').append(_("Download and verify only")).append("</option>");
    140140       
     
    142142            buf.append("<option value=\"install\"");
    143143            if (_dontInstall)
    144                 buf.append(" disabled=\"true\"");
     144                buf.append(" disabled=\"disabled\"");
    145145            else if ("install".equals(policy))
    146                 buf.append(" selected=\"true\"");
     146                buf.append(" selected=\"selected\"");
    147147            buf.append('>').append(_("Download, verify, and restart")).append("</option>");
    148148        }
  • apps/routerconsole/java/src/net/i2p/router/web/FileDumpHelper.java

    rf43b0be r2b81cee  
    1919import net.i2p.crypto.SHA256Generator;
    2020import net.i2p.data.DataHelper;
     21import net.i2p.util.FileUtil;
    2122
    2223/**
     
    3031        StringBuilder buf = new StringBuilder(16*1024);
    3132        buf.append("<table><tr><th>File</th><th>Size</th><th>Date</th><th>SHA 256</th><th>Revision</th>" +
    32                    "<th>JDK</th><th>Built</th><th>Mods</th></tr>");
     33                   "<th>JDK</th><th>Built</th><th>By</th><th>Mods</th></tr>");
    3334
    3435        // jars added in wrapper.config
     
    9697        else
    9798            buf.append("<font color=\"red\">Not found</font>");
    98         buf.append("</td><td>");
     99        buf.append("</td><td align=\"center\">");
     100        if (mod > 0 && !FileUtil.verifyZip(f))
     101            buf.append("<font color=\"red\">CORRUPT</font><br>");
    99102        byte[] hash = sha256(f);
    100103        if (hash != null) {
     
    135138        if (s != null)
    136139            buf.append(s);
     140        buf.append("</td><td align=\"center\">");
     141        s = getAtt(att, "Built-By");
     142        if (s != null)
     143            buf.append(s);
    137144        buf.append("</td><td><font color=\"red\">");
    138145        s = getAtt(att, "Workspace-Changes");
    139146        if (s != null)
    140147            buf.append(s.replace(",", "<br>"));
    141         buf.append("</font></td>");
     148        buf.append("</font></td></tr>\n");
    142149    }
    143150
  • apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java

    rf43b0be r2b81cee  
    2121    private int _refreshDelaySeconds;
    2222    private boolean _persistent;
     23    private String _stat;
     24    private int _end;
    2325
    2426    private static final String PROP_X = "routerconsole.graphX";
     
    3335    static final int MAX_X = 2048;
    3436    static final int MAX_Y = 1024;
     37    private static final int MIN_X = 200;
     38    private static final int MIN_Y = 60;
     39    private static final int MIN_C = 20;
     40    private static final int MAX_C = SummaryListener.MAX_ROWS;
    3541    private static final int MIN_REFRESH = 15;
    3642   
     
    6571
    6672    public void setPeriodCount(String str) {
    67         try { _periodCount = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
    68     }
    69 
    70     public void setShowEvents(boolean b) { _showEvents = b; }
     73        setC(str);
     74    }
     75
     76    /** @since 0.9 */
     77    public void setE(String str) {
     78        try {
     79            _end = Math.max(0, Integer.parseInt(str));
     80        } catch (NumberFormatException nfe) {}
     81    }
     82
     83    /** @since 0.9 shorter parameter */
     84    public void setC(String str) {
     85        try {
     86            _periodCount = Math.max(MIN_C, Math.min(Integer.parseInt(str), MAX_C));
     87        } catch (NumberFormatException nfe) {}
     88    }
     89
     90    public void setShowEvents(String b) { _showEvents = !"false".equals(b); }
    7191
    7292    public void setHeight(String str) {
    73         try { _height = Math.min(Integer.parseInt(str), MAX_Y); } catch (NumberFormatException nfe) {}
     93        setH(str);
     94    }
     95
     96    /** @since 0.9 shorter parameter */
     97    public void setH(String str) {
     98        try {
     99            _height = Math.max(MIN_Y, Math.min(Integer.parseInt(str), MAX_Y));
     100        } catch (NumberFormatException nfe) {}
    74101    }
    75102
    76103    public void setWidth(String str) {
    77         try { _width = Math.min(Integer.parseInt(str), MAX_X); } catch (NumberFormatException nfe) {}
     104        setW(str);
     105    }
     106
     107    /** @since 0.9 shorter parameter */
     108    public void setW(String str) {
     109        try {
     110            _width = Math.max(MIN_X, Math.min(Integer.parseInt(str), MAX_X));
     111        } catch (NumberFormatException nfe) {}
    78112    }
    79113
     
    90124    /** @since 0.8.7 */
    91125    public void setPersistent(String foo) { _persistent = true; }
     126
     127    /**
     128     *  For single stat page
     129     *  @since 0.9
     130     */
     131    public void setStat(String stat) {
     132        _stat = stat;
     133    }
    92134   
    93135    public String getImages() {
     
    110152
    111153            if (hasTx && hasRx && !_showEvents) {
    112                 _out.write("<a href=\"viewstat.jsp?stat=bw.combined"
     154                _out.write("<a href=\"viewstat?stat=bw.combined"
    113155                           + "&amp;periodCount=" + (3 * _periodCount )
    114156                           + "&amp;width=" + (3 * _width)
    115157                           + "&amp;height=" + (3 * _height)
    116                            + "\" target=\"_blank\">");
     158                           + "\">");
    117159                String title = _("Combined bandwidth graph");
    118160                _out.write("<img class=\"statimage\""
     
    129171                // e.g. "statname for 60m"
    130172                String title = _("{0} for {1}", r.getRateStat().getName(), DataHelper.formatDuration2(_periodCount * r.getPeriod()));
    131                 _out.write("<a href=\"viewstat.jsp?stat="
     173                _out.write("<a href=\"graph?stat="
    132174                           + r.getRateStat().getName()
    133                            + "&amp;showEvents=" + _showEvents
    134                            + "&amp;period=" + r.getPeriod()
    135                            + "&amp;periodCount=" + (3 * _periodCount)
    136                            + "&amp;width=" + (3 * _width)
    137                            + "&amp;height=" + (3 * _height)
    138                            + "\" target=\"_blank\">");
     175                           + '.' + r.getPeriod()
     176                           + "&amp;c=" + (3 * _periodCount)
     177                           + "&amp;w=" + (3 * _width)
     178                           + "&amp;h=" + (3 * _height)
     179                           + (_showEvents ? "&amp;showEvents=1" : "")
     180                           + "\">");
    139181                _out.write("<img class=\"statimage\" border=\"0\""
    140182                           + " src=\"viewstat.jsp?stat="
     
    157199    }
    158200
     201    /**
     202     *  For single stat page
     203     *  @since 0.9
     204     */
     205    public String getSingleStat() {
     206        try {
     207            if (StatSummarizer.isDisabled())
     208                return "";
     209            if (_stat == null) {
     210                _out.write("No stat");
     211                return "";
     212            }
     213            List<Rate> rates = StatSummarizer.instance().parseSpecs(_stat);
     214            if (rates.size() != 1) {
     215                _out.write("Graphs not enabled for " + _stat);
     216                return "";
     217            }
     218            Rate r = rates.get(0);
     219            _out.write("<h3>");
     220            _out.write(_("{0} for {1}", r.getRateStat().getName(), DataHelper.formatDuration2(_periodCount * r.getPeriod())));
     221            if (_end > 0)
     222                _out.write(' ' + _("ending {0} ago", DataHelper.formatDuration2(_end * r.getPeriod())));
     223
     224            _out.write("</h3><p><img class=\"statimage\" border=\"0\""
     225                       + " src=\"viewstat.jsp?stat="
     226                       + r.getRateStat().getName()
     227                       + "&amp;showEvents=" + _showEvents
     228                       + "&amp;period=" + r.getPeriod()
     229                       + "&amp;periodCount=" + _periodCount
     230                       + "&amp;end=" + _end
     231                       + "&amp;width=" + _width
     232                       + "&amp;height=" + _height
     233                       + "\"></p><p>\n");
     234
     235            if (_width < MAX_X && _height < MAX_Y) {
     236                _out.write(link(_stat, _showEvents, _periodCount, _end, _width * 3 / 2, _height * 3 / 2));
     237                _out.write(_("Larger"));
     238                _out.write("</a> - ");
     239            }
     240
     241            if (_width > MIN_X && _height > MIN_Y) {
     242                _out.write(link(_stat, _showEvents, _periodCount, _end, _width * 2 / 3, _height * 2 / 3));
     243                _out.write(_("Smaller"));
     244                _out.write("</a> - ");
     245            }
     246
     247            if (_height < MAX_Y) {
     248                _out.write(link(_stat, _showEvents, _periodCount, _end, _width, _height * 3 / 2));
     249                _out.write(_("Taller"));
     250                _out.write("</a> - ");
     251            }
     252
     253            if (_height > MIN_Y) {
     254                _out.write(link(_stat, _showEvents, _periodCount, _end, _width, _height * 2 / 3));
     255                _out.write(_("Shorter"));
     256                _out.write("</a> - ");
     257            }
     258
     259            if (_width < MAX_X) {
     260                _out.write(link(_stat, _showEvents, _periodCount, _end, _width * 3 / 2, _height));
     261                _out.write(_("Wider"));
     262                _out.write("</a> - ");
     263            }
     264
     265            if (_width > MIN_X) {
     266                _out.write(link(_stat, _showEvents, _periodCount, _end, _width * 2 / 3, _height));
     267                _out.write(_("Narrower"));
     268                _out.write("</a>");
     269            }
     270
     271            _out.write("<br>");
     272            if (_periodCount < MAX_C) {
     273                _out.write(link(_stat, _showEvents, _periodCount * 2, _end, _width, _height));
     274                _out.write(_("Larger interval"));
     275                _out.write("</a> - ");
     276            }
     277
     278            if (_periodCount > MIN_C) {
     279                _out.write(link(_stat, _showEvents, _periodCount / 2, _end, _width, _height));
     280                _out.write(_("Smaller interval"));
     281                _out.write("</a>");
     282            }
     283
     284            _out.write("<br>");
     285            if (_periodCount < MAX_C) {
     286                _out.write(link(_stat, _showEvents, _periodCount, _end + _periodCount, _width, _height));
     287                _out.write(_("Previous interval"));
     288                _out.write("</a>");
     289            }
     290
     291            if (_end > 0) {
     292                int end = _end - _periodCount;
     293                if (end <= 0)
     294                    end = 0;
     295                if (_periodCount < MAX_C)
     296                    _out.write(" - ");
     297                _out.write(link(_stat, _showEvents, _periodCount, end, _width, _height));
     298                _out.write(_("Next interval"));
     299                _out.write("</a> ");
     300            }
     301
     302            _out.write("<br>");
     303            _out.write(link(_stat, !_showEvents, _periodCount, _end, _width, _height));
     304            _out.write(_showEvents ? _("Plot averages") : _("plot events"));
     305            _out.write("</a>");
     306
     307            _out.write("</p><p><i>" + _("All times are UTC.") + "</i></p>\n");
     308        } catch (IOException ioe) {
     309            ioe.printStackTrace();
     310        }
     311        return "";
     312    }
     313
     314    /** @since 0.9 */
     315    private static String link(String stat, boolean showEvents,
     316                               int periodCount, int end,
     317                               int width, int height) {
     318        return
     319               "<a href=\"graph?stat="
     320               + stat
     321               + "&amp;c=" + periodCount
     322               + "&amp;w=" + width
     323               + "&amp;h=" + height
     324               + (end > 0 ? "&amp;e=" + end : "")
     325               + (showEvents ? "&amp;showEvents=1" : "")
     326               + "\">";
     327    }
     328
    159329    private static final int[] times = { 60, 2*60, 5*60, 10*60, 30*60, 60*60, -1 };
    160330
     
    172342                       "<input type=\"hidden\" name=\"nonce\" value=\"" + nonce + "\" >\n");
    173343            _out.write(_("Periods") + ": <input size=\"5\" style=\"text-align: right;\" type=\"text\" name=\"periodCount\" value=\"" + _periodCount + "\"><br>\n");
    174             _out.write(_("Plot averages") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"false\" " + (_showEvents ? "" : "checked=\"true\" ") + "> ");
    175             _out.write(_("or")+ " " +_("plot events") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"true\" "+ (_showEvents ? "checked=\"true\" " : "") + "><br>\n");
     344            _out.write(_("Plot averages") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"false\" " + (_showEvents ? "" : "checked=\"checked\" ") + "> ");
     345            _out.write(_("or")+ " " +_("plot events") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"true\" "+ (_showEvents ? "checked=\"checked\" " : "") + "><br>\n");
    176346            _out.write(_("Image sizes") + ": " + _("width") + ": <input size=\"4\" style=\"text-align: right;\" type=\"text\" name=\"width\" value=\"" + _width
    177347                       + "\"> " + _("pixels") + ", " + _("height") + ": <input size=\"4\" style=\"text-align: right;\" type=\"text\" name=\"height\" value=\"" + _height 
     
    183353                _out.write("\"");
    184354                if (times[i] == _refreshDelaySeconds)
    185                     _out.write(" selected=\"true\"");
     355                    _out.write(" selected=\"selected\"");
    186356                _out.write(">");
    187357                if (times[i] > 0)
     
    196366            boolean persistent = _context.getBooleanPropertyDefaultTrue(SummaryListener.PROP_PERSISTENT);
    197367            if (persistent)
    198                 _out.write(" checked=\"true\"");
     368                _out.write(" checked=\"checked\"");
    199369            _out.write(">" +
    200370                       "<hr><div class=\"formaction\"><input type=\"submit\" class=\"acceot\" value=\"" + _("Save settings and redraw graphs") + "\"></div></form>");
  • apps/routerconsole/java/src/net/i2p/router/web/NavHelper.java

    rf43b0be r2b81cee  
    3737    /**
    3838     *  Translated string is loaded by PluginStarter
     39     *  @param ctx unused
    3940     */
    4041    public static String getClientAppLinks(I2PAppContext ctx) {
     
    5657        return buf.toString();
    5758    }
     59   
     60    /**
     61     *  For HomeHelper
     62     *  @param ctx unused
     63     *  @return non-null, possibly empty
     64     *  @since 0.9
     65     */
     66    static List<HomeHelper.App> getClientApps(I2PAppContext ctx) {
     67        if (_apps.isEmpty())
     68            return Collections.EMPTY_LIST;
     69        List<HomeHelper.App> rv = new ArrayList(_apps.size());
     70        for (Map.Entry<String, String> e : _apps.entrySet()) {
     71            String name = e.getKey();
     72            String path = e.getValue();
     73            if (path == null)
     74                continue;
     75            String tip = _tooltips.get(name);
     76            if (tip == null)
     77                tip = "";
     78            // hardcoded hack
     79            String icon;
     80            if (path.equals("/i2pbote/index.jsp"))
     81                icon = "/themes/console/images/email.png";
     82            else
     83                icon = "/themes/console/images/plugin.png";
     84            HomeHelper.App app = new HomeHelper.App(name, tip, path, icon);
     85            rv.add(app);
     86        }
     87        return rv;
     88    }
    5889}
  • apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java

    rf43b0be r2b81cee  
    3434import net.i2p.router.TunnelPoolSettings;
    3535import net.i2p.router.networkdb.kademlia.HashDistance;   // debug
     36import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
    3637import net.i2p.util.HexDump;                             // debug
    3738import net.i2p.util.ObjectCounter;
     
    106107        buf.append("<h2>" + _("Network Database Contents") + "</h2>\n");
    107108        buf.append("<a href=\"netdb\">" + _("View RouterInfo") + "</a>");
    108         buf.append("<h3>").append(_("LeaseSets")).append("</h3>\n");
     109        buf.append("<h3>").append(_("LeaseSets"));
     110        if (debug)
     111            buf.append(" - Debug mode - Sorted by hash distance, closest first");
     112        buf.append("</h3>\n");
    109113        Hash ourRKey;
    110114        Set<LeaseSet> leases;
     
    121125        leases.addAll(_context.netDb().getLeases());
    122126        int medianCount = 0;
     127        int rapCount = 0;
    123128        BigInteger median = null;
    124129        int c = 0;
     
    127132            for (LeaseSet ls : leases) {
    128133                if (ls.getReceivedAsPublished())
    129                     medianCount++;
    130             }
    131             medianCount /= 2;
     134                    rapCount++;
     135            }
     136            medianCount = rapCount / 2;
    132137        }
    133138        long now = _context.clock().now();
     
    168173                        median = dist;
    169174                }
    170                 buf.append(" Dist: <b>").append(fmt.format(biLog2(dist))).append("</b>");
    171                 buf.append(" RKey: ").append(ls.getRoutingKey().toBase64());
     175                buf.append(" Dist: <b>").append(fmt.format(biLog2(dist))).append("</b><br>");
     176                buf.append("Routing Key: ").append(ls.getRoutingKey().toBase64());
    172177                buf.append("<br>");
     178                buf.append("Encryption Key: ").append(ls.getEncryptionKey().toBase64().substring(0, 20)).append("...<br>");
    173179            }
    174180            for (int i = 0; i < ls.getLeaseCount(); i++) {
     
    182188        }
    183189        if (debug) {
    184             buf.append("<p><b>Total Leasesets: " + leases.size());
    185             buf.append("</b></p><p><b>Published (RAP) Leasesets: " + _context.netDb().getKnownLeaseSets());
     190            FloodfillNetworkDatabaseFacade netdb = (FloodfillNetworkDatabaseFacade)_context.netDb();
     191            buf.append("<p><b>Total Leasesets: ").append(leases.size());
     192            buf.append("</b></p><p><b>Published (RAP) Leasesets: ").append(netdb.getKnownLeaseSets());
    186193            //buf.append("</b></p><p><b>Mod Data: " + HexDump.dump(_context.routingKeyGenerator().getModData()));
     194            int ff = _context.peerManager().getPeersByCapability(FloodfillNetworkDatabaseFacade.CAPABILITY_FLOODFILL).size();
     195            buf.append("</b></p><p><b>Known Floodfills: ").append(ff);
     196            buf.append("</b></p><p><b>Currently Floodfill? ");
     197            buf.append(netdb.floodfillEnabled() ? "yes" : "no");
    187198            buf.append("</b></p><p><b>Network data (only valid if floodfill):");
    188199            //buf.append("</b></p><p><b>Center of Key Space (router hash): " + ourRKey.toBase64());
    189200            if (median != null) {
    190201                double log2 = biLog2(median);
    191                 buf.append("</b></p><p><b>Median distance (bits): " + fmt.format(log2));
     202                buf.append("</b></p><p><b>Median distance (bits): ").append(fmt.format(log2));
    192203                // 3 for 8 floodfills... -1 for median
    193204                int total = (int) Math.round(Math.pow(2, 3 + 256 - 1 - log2));
    194                 buf.append("</b></p><p><b>Estimated total floodfills: " + total);
    195                 buf.append("</b></p><p><b>Estimated network total leasesets: " + (total * leases.size() / 8));
     205                buf.append("</b></p><p><b>Estimated total floodfills: ").append(total);
     206                buf.append("</b></p><p><b>Estimated total leasesets: ").append(total * rapCount / 8);
    196207            }
    197208            buf.append("</b></p>");
  • apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java

    rf43b0be r2b81cee  
    173173    public boolean renderPng(Rate rate, OutputStream out) throws IOException {
    174174        return renderPng(rate, out, GraphHelper.DEFAULT_X, GraphHelper.DEFAULT_Y,
    175                          false, false, false, false, -1, true);
     175                         false, false, false, false, -1, 0, true);
    176176    }
    177177
     
    180180     *  For the two-data bandwidth graph see renderRatePng().
    181181     *  Synchronized to conserve memory.
     182     *
     183     *  @param end number of periods before now
    182184     *  @return success
    183185     */
    184186    public boolean renderPng(Rate rate, OutputStream out, int width, int height, boolean hideLegend,
    185187                                          boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount,
    186                                           boolean showCredit) throws IOException {
     188                                          int end, boolean showCredit) throws IOException {
    187189        try {
    188190            try {
     
    190192            } catch (InterruptedException ie) {}
    191193            return locked_renderPng(rate, out, width, height, hideLegend, hideGrid, hideTitle, showEvents,
    192                                     periodCount, showCredit);
     194                                    periodCount, end, showCredit);
    193195        } finally {
    194196            _sem.release();
     
    196198    }
    197199
     200    /**
     201     *  @param end number of periods before now
     202     */
    198203    private boolean locked_renderPng(Rate rate, OutputStream out, int width, int height, boolean hideLegend,
    199204                                          boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount,
    200                                           boolean showCredit) throws IOException {
     205                                          int end, boolean showCredit) throws IOException {
    201206        if (width > GraphHelper.MAX_X)
    202207            width = GraphHelper.MAX_X;
     
    207212        else if (height <= 0)
    208213            height = GraphHelper.DEFAULT_Y;
     214        if (end < 0)
     215            end = 0;
    209216        for (SummaryListener lsnr : _listeners) {
    210217            if (lsnr.getRate().equals(rate)) {
    211                 lsnr.renderPng(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit);
     218                lsnr.renderPng(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, end, showCredit);
    212219                return true;
    213220            }
     
    369376     * @return list of Rate objects
    370377     */
    371     private List<Rate> parseSpecs(String specs) {
     378    List<Rate> parseSpecs(String specs) {
    372379        StringTokenizer tok = new StringTokenizer(specs, ",");
    373380        List<Rate> rv = new ArrayList();
  • apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java

    rf43b0be r2b81cee  
    267267        buf.setLength(0);
    268268
    269 
    270         boolean anotherLine = false;
    271         if (_helper.showFirewallWarning()) {
    272             buf.append("<h4><a href=\"/confignet\" target=\"_top\" title=\"")
    273                .append(_("Help with firewall configuration"))
    274                .append("\">")
    275                .append(_("Check network connection and NAT/firewall"))
    276                .append("</a></h4>");
    277             anotherLine = true;
    278         }
    279 
    280         boolean reseedInProgress = Boolean.valueOf(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress")).booleanValue();
    281         // If showing the reseed link is allowed
    282         if (_helper.allowReseed()) {
    283             if (reseedInProgress) {
    284                 // While reseed occurring, show status message instead
    285                 buf.append("<i>").append(System.getProperty("net.i2p.router.web.ReseedHandler.statusMessage","")).append("</i><br>");
    286             } else {
    287                 // While no reseed occurring, show reseed link
    288                 long nonce = _context.random().nextLong();
    289                 String prev = System.getProperty("net.i2p.router.web.ReseedHandler.nonce");
    290                 if (prev != null) System.setProperty("net.i2p.router.web.ReseedHandler.noncePrev", prev);
    291                 System.setProperty("net.i2p.router.web.ReseedHandler.nonce", nonce+"");
    292                 String uri = _helper.getRequestURI();
    293                 buf.append("<p><form action=\"").append(uri).append("\" method=\"POST\">\n");
    294                 buf.append("<input type=\"hidden\" name=\"reseedNonce\" value=\"").append(nonce).append("\" >\n");
    295                 buf.append("<button type=\"submit\" class=\"reload\" value=\"Reseed\" >").append(_("Reseed")).append("</button></form></p>\n");
    296             }
    297             anotherLine = true;
    298         }
    299         // If a new reseed ain't running, and the last reseed had errors, show error message
    300         if (!reseedInProgress) {
    301             String reseedErrorMessage = System.getProperty("net.i2p.router.web.ReseedHandler.errorMessage","");
    302             if (reseedErrorMessage.length() > 0) {
    303                 buf.append("<i>").append(reseedErrorMessage).append("</i><br>");
    304                 anotherLine = true;
    305             }
    306         }
    307         if (anotherLine)
    308             buf.append("<hr>");
    309 
     269        buf.append(_helper.getFirewallAndReseedStatus());
    310270
    311271        buf.append("<h3><a href=\"/config\" title=\"")
  • apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java

    rf43b0be r2b81cee  
    663663    }
    664664
     665    /**
     666     *  The firewall status and reseed status/buttons
     667     *  @since 0.9 moved from SummaryBarRenderer
     668     */
     669    public String getFirewallAndReseedStatus() {
     670        StringBuilder buf = new StringBuilder(256);
     671        if (showFirewallWarning()) {
     672            buf.append("<h4><a href=\"/confignet\" target=\"_top\" title=\"")
     673               .append(_("Help with firewall configuration"))
     674               .append("\">")
     675               .append(_("Check network connection and NAT/firewall"))
     676               .append("</a></h4>");
     677        }
     678
     679        boolean reseedInProgress = Boolean.valueOf(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress")).booleanValue();
     680        // If showing the reseed link is allowed
     681        if (allowReseed()) {
     682            if (reseedInProgress) {
     683                // While reseed occurring, show status message instead
     684                buf.append("<i>").append(System.getProperty("net.i2p.router.web.ReseedHandler.statusMessage","")).append("</i><br>");
     685            } else {
     686                // While no reseed occurring, show reseed link
     687                long nonce = _context.random().nextLong();
     688                String prev = System.getProperty("net.i2p.router.web.ReseedHandler.nonce");
     689                if (prev != null) System.setProperty("net.i2p.router.web.ReseedHandler.noncePrev", prev);
     690                System.setProperty("net.i2p.router.web.ReseedHandler.nonce", nonce+"");
     691                String uri = getRequestURI();
     692                buf.append("<p><form action=\"").append(uri).append("\" method=\"POST\">\n");
     693                buf.append("<input type=\"hidden\" name=\"reseedNonce\" value=\"").append(nonce).append("\" >\n");
     694                buf.append("<button type=\"submit\" class=\"reload\" value=\"Reseed\" >").append(_("Reseed")).append("</button></form></p>\n");
     695            }
     696        }
     697        // If a new reseed ain't running, and the last reseed had errors, show error message
     698        if (!reseedInProgress) {
     699            String reseedErrorMessage = System.getProperty("net.i2p.router.web.ReseedHandler.errorMessage","");
     700            if (reseedErrorMessage.length() > 0) {
     701                buf.append("<i>").append(reseedErrorMessage).append("</i><br>");
     702            }
     703        }
     704        if (buf.length() <= 0)
     705            return "";
     706        buf.append("<hr>");
     707        return buf.toString();
     708    }
     709
    665710    /** output the summary bar to _out */
    666711    public void renderSummaryBar() throws IOException {
  • apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java

    rf43b0be r2b81cee  
    5656    static final int PERIODS = 60 * 24;  // 1440
    5757    private static final int MIN_ROWS = PERIODS;
    58     private static final int MAX_ROWS = 91 * MIN_ROWS;
     58    static final int MAX_ROWS = 91 * MIN_ROWS;
    5959    private static final long THREE_MONTHS = 91l * 24 * 60 * 60 * 1000;
    6060   
     
    192192    }
    193193
    194     public void renderPng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, boolean showCredit) throws IOException {
     194    /**
     195     *  @param end number of periods before now
     196     */
     197    public void renderPng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid,
     198                          boolean hideTitle, boolean showEvents, int periodCount,
     199                          int end, boolean showCredit) throws IOException {
    195200        if (_renderer == null || _db == null)
    196201            throw new IOException("No RRD, check logs for previous errors");
    197         _renderer.render(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit);
     202        _renderer.render(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, end, showCredit);
    198203    }
    199204
  • apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java

    rf43b0be r2b81cee  
    8282
    8383    public void render(OutputStream out) throws IOException { render(out, GraphHelper.DEFAULT_X, GraphHelper.DEFAULT_Y,
    84                                                                      false, false, false, false, -1, false); }
    85 
    86     public void render(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, boolean showCredit) throws IOException {
     84                                                                     false, false, false, false, -1, 0, false); }
     85
     86    /**
     87     *  @param endp number of periods before now
     88     */
     89    public void render(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid,
     90                       boolean hideTitle, boolean showEvents, int periodCount,
     91                       int endp, boolean showCredit) throws IOException {
    8792        long end = _listener.now() - 75*1000;
     93        long period = _listener.getRate().getPeriod();
     94        if (endp > 0)
     95            end -= period * endp;
    8896        if (periodCount <= 0 || periodCount > _listener.getRows())
    8997            periodCount = _listener.getRows();
    90         long start = end - _listener.getRate().getPeriod()*periodCount;
     98        long start = end - (period * periodCount);
    9199        //long begin = System.currentTimeMillis();
    92100        try {
     
    104112                // we want the formatting and translation of formatDuration2(), except not zh, and not the &nbsp;
    105113                if (IS_WIN && "zh".equals(Messages.getLanguage(_context)))
    106                     p = DataHelper.formatDuration(_listener.getRate().getPeriod());
     114                    p = DataHelper.formatDuration(period);
    107115                else
    108                     p = DataHelper.formatDuration2(_listener.getRate().getPeriod()).replace("&nbsp;", " ");
     116                    p = DataHelper.formatDuration2(period).replace("&nbsp;", " ");
    109117                if (showEvents)
    110118                    title = name + ' ' + _("events in {0}", p);
  • apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java

    rf43b0be r2b81cee  
    135135        out.write("<div class=\"statusnotes\"><b>" + _("Lifetime bandwidth usage") + ": " + DataHelper.formatSize2(processed*1024) + "B</b></div>\n");
    136136        //renderPeers(out);
     137        out.write("</div>");
    137138    }
    138139   
     
    223224        }
    224225        if (live <= 0)
    225             out.write("<div class=\"statusnotes\"><center><b>" + _("No tunnels; waiting for the grace period to end.") + "</center></b></div>\n");
     226            out.write("<div class=\"statusnotes\"><center><b>" + _("No tunnels; waiting for the grace period to end.") + "</b></center></div>\n");
    226227        out.write("<div class=\"statusnotes\"><center><b>" + _("Lifetime bandwidth usage") + ": " +
    227228                  DataHelper.formatSize2(processedIn*1024) + "B " + _("in") + ", " +
  • apps/routerconsole/jsp/configreseed.jsp

    rf43b0be r2b81cee  
    4343<b><%=intl._("Use non-SSL only")%></b></td></tr>
    4444<tr><td class="mediumtags" align="right"><b><%=intl._("Reseed URLs")%>:</b></td>
    45 <td><textarea name="reseedURL" wrap="off" spellcheck="false"><jsp:getProperty name="reseedHelper" property="reseedURL" /></textarea></td></tr>
     45<td><textarea wrap="off" name="reseedURL" cols="60" rows="7" spellcheck="false"><jsp:getProperty name="reseedHelper" property="reseedURL" /></textarea></td></tr>
    4646
    4747<tr><td class="mediumtags" align="right"><b><%=intl._("Enable HTTP Proxy?")%></b></td>
  • apps/routerconsole/jsp/configstats.jsp

    rf43b0be r2b81cee  
    7878 <p><%=intl._("Enable full stats?")%>
    7979 <input type="checkbox" class="optbox" name="isFull" value="true" <%
    80  if (statshelper.getIsFull()) { %>checked="true" <% } %> >
     80 if (statshelper.getIsFull()) { %>checked="checked" <% } %> >
    8181 (<%=intl._("change requires restart to take effect")%>)<br>
    82  <%=intl._("Stat file")%>: <input type="text" name="filename" value="<%=statshelper.getFilename()%>" ><br>
    83 <%=intl._("Filter")%>: (<a href="javascript:void(null);" onclick="toggleAll('*')"><%=intl._("toggle all")%></a>)<br></p>
     82<%
     83
     84  // stats.log for devs only and grows without bounds, not recommended
     85  boolean shouldShowLog = statshelper.shouldShowLog();
     86  if (shouldShowLog) {
     87
     88%><%=intl._("Stat file")%>: <input type="text" name="filename" value="<%=statshelper.getFilename()%>" ><br>
     89Warning - Log with care, stat file grows without limit.<br>
     90<%
     91
     92  }  // shouldShowLog
     93
     94%><%=intl._("Filter")%>: (<a href="javascript:void(null);" onclick="toggleAll('*')"><%=intl._("toggle all")%></a>)<br></p>
    8495 <div class="wideload">
    8596 <table>
     
    92103     </td></tr>
    93104 <tr class="tablefooter">
    94     <td align="center"><b><%=intl._("Log")%></b></td>
    95     <td align="center"><b><%=intl._("Graph")%></b></td>
     105<%
     106
     107  if (shouldShowLog) {
     108
     109%>  <td align="center"><b><%=intl._("Log")%></b></td>
     110<%
     111
     112  }  // shouldShowLog
     113
     114%>    <td align="center"><b><%=intl._("Graph")%></b></td>
    96115    <td></td></tr>
    97116        <%
    98117     } // end iterating over required groups for the current stat %>
    99  <tr><td align="center">
     118 <tr>
     119<%
     120
     121  if (shouldShowLog) {
     122
     123%>   <td align="center">
    100124     <a name="<%=statshelper.getCurrentStatName()%>"></a>
    101125     <input type="checkbox" class="optbox <%=statshelper.getCurrentGroupName()%>" name="statList" value="<%=statshelper.getCurrentStatName()%>" <%
    102      if (statshelper.getCurrentIsLogged()) { %>checked="true" <% } %> ></td>
    103      <td align="center">
     126     if (statshelper.getCurrentIsLogged()) { %>checked="checked" <% } %> ></td>
     127<%
     128
     129  }  // shouldShowLog
     130
     131%>   <td align="center">
    104132     <% if (statshelper.getCurrentCanBeGraphed()) { %>
    105133       <input type="checkbox" class="optbox <%=statshelper.getCurrentGroupName()%>" name="graphList" value="<%=statshelper.getCurrentGraphName()%>" <%
    106        if (statshelper.getCurrentIsGraphed()) { %>checked="true" <% } %> ><% } %></td>
     134       if (statshelper.getCurrentIsGraphed()) { %>checked="checked" <% } %> ><% } %></td>
    107135     <td align="left"><b><%=statshelper.getCurrentStatName()%>:</b><br>
    108136     <%=statshelper.getCurrentStatDescription()%></td></tr><%
    109     } // end iterating over all stats %>
    110  <tr><td colspan="3"></td></tr>
     137    } // end iterating over all stats
     138
     139  if (shouldShowLog) {
     140
     141%> <tr><td colspan="3"></td></tr>
    111142 <tr><td align="center"><input type="checkbox" class="optbox" name="explicitFilter" ></td>
    112143     <td colspan="2"><%=intl._("Advanced filter")%>:
    113144     <input type="text" name="explicitFilterValue" value="<%=statshelper.getExplicitFilter()%>" size="40" ></td></tr>
    114      <tr class="tablefooter"><td colspan="3" align="right">
     145<%
     146
     147  }  // shouldShowLog
     148
     149%>   <tr class="tablefooter"><td colspan="3" align="right">
    115150<input type="reset" class="cancel" value="<%=intl._("Cancel")%>" >
    116151<input type="submit" name="shouldsave" class="accept" value="<%=intl._("Save changes")%>" >
  • apps/routerconsole/jsp/configupdate.jsp

    rf43b0be r2b81cee  
    5858    <% if (updatehelper.canInstall()) { %>
    5959        <tr><td class= "mediumtags" align="right"><b><%=intl._("Update URLs")%>:</b></td>
    60           <td><textarea name="updateURL" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea></td>
     60          <td><textarea cols="60" rows="6" name="updateURL" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea></td>
    6161        </tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Trusted keys")%>:</b></td>
    62           <td><textarea name="trustedKeys" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></td>
     62          <td><textarea cols="60" rows="6" name="trustedKeys" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></td>
    6363        </tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Update with unsigned development builds?")%></b></td>
    6464          <td><jsp:getProperty name="updatehelper" property="updateUnsigned" /></td>
  • apps/routerconsole/jsp/graphs.jsp

    rf43b0be r2b81cee  
    88<%=intl.title("graphs")%>
    99 <jsp:useBean class="net.i2p.router.web.GraphHelper" id="graphHelper" scope="request" />
    10  <% graphHelper.storeMethod(request.getMethod()); %>
    1110 <jsp:setProperty name="graphHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
    1211<% /* GraphHelper sets the defaults in setContextId, so setting the properties must be after the context */ %>
  • apps/routerconsole/jsp/index.jsp

    rf43b0be r2b81cee  
    1 <%@page contentType="text/html"%>
    2 <%@page trimDirectiveWhitespaces="true"%>
     1<%@page contentType="text/plain"%>
    32<%@page pageEncoding="UTF-8"%>
    4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    5 
    6 <html><head>
    7 <%@include file="css.jsi" %>
    8 <%=intl.title("home")%>
    9 </head><body>
    103<%
    11     String consoleNonce = System.getProperty("router.consoleNonce");
    12     if (consoleNonce == null) {
    13         consoleNonce = Long.toString(new java.util.Random().nextLong());
    14         System.setProperty("router.consoleNonce", consoleNonce);
    15     }
     4    //
     5    //  Redirect to either /home or /console, depending on configuration,
     6    //  while preserving any query parameters
     7    //
     8    response.setStatus(302, "Moved");
     9    String req = request.getRequestURL().toString();
     10    StringBuilder buf = new StringBuilder(128);
     11    if (req.endsWith("index"))
     12        req = req.substring(0, req.length() - 5);
     13    else if (req.endsWith("index.jsp"))
     14        req = req.substring(0, req.length() - 9);
     15    buf.append(req);
     16    if (!req.endsWith("/"))
     17        buf.append('/');
     18    boolean oldHome = net.i2p.I2PAppContext.getGlobalContext().getBooleanProperty("routerconsole.oldHomePage");
     19    if (oldHome)
     20        buf.append("console");
     21    else
     22        buf.append("home");
     23    String query = request.getQueryString();
     24    if (query != null)
     25        buf.append('?').append(query);
     26    response.setHeader("Location", buf.toString());
    1627%>
    17 
    18 <%@include file="summary.jsi" %><h1><%=intl._("I2P Router Console")%></h1>
    19 <div class="news" id="news">
    20  <jsp:useBean class="net.i2p.router.web.NewsHelper" id="newshelper" scope="request" />
    21  <jsp:setProperty name="newshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
    22 <%
    23    if (newshelper.shouldShowNews()) {
    24        java.io.File fpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getRouterDir(), "docs/news.xml");
    25 %>
    26  <jsp:setProperty name="newshelper" property="page" value="<%=fpath.getAbsolutePath()%>" />
    27  <jsp:setProperty name="newshelper" property="maxLines" value="300" />
    28  <jsp:getProperty name="newshelper" property="content" />
    29  <hr>
    30 <%
    31    }  // shouldShowNews()
    32 %>
    33  <jsp:useBean class="net.i2p.router.web.ConfigUpdateHelper" id="updatehelper" scope="request" />
    34  <jsp:setProperty name="updatehelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
    35  <jsp:getProperty name="updatehelper" property="newsStatus" /><br>
    36 </div><div class="main" id="main">
    37  <jsp:useBean class="net.i2p.router.web.ContentHelper" id="contenthelper" scope="request" />
    38  <div class="welcome">
    39   <div class="langbox"> <% /* English, then alphabetical by English name please */ %>
    40     <a href="/?lang=en&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=us" title="English" alt="English"></a>
    41     <a href="/?lang=ar&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=lang_ar" title="عربية" alt="عربية"></a>
    42     <a href="/?lang=zh&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=cn" title="中文" alt="中文"></a>
    43     <a href="/?lang=cs&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=cz" title="Czech" alt="Czech"></a>
    44     <a href="/?lang=da&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=dk" title="Danish" alt="Danish"></a>
    45     <a href="/?lang=de&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=de" title="Deutsch" alt="Deutsch"></a>
    46     <a href="/?lang=ee&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=ee" title="Eesti" alt="Eesti"></a>
    47     <a href="/?lang=es&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=es" title="Español" alt="Español"></a>
    48     <a href="/?lang=fi&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=fi" title="Suomi" alt="Suomi"></a><br>
    49     <a href="/?lang=fr&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=fr" title="Français" alt="Français"></a>
    50     <a href="/?lang=it&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=it" title="Italiano" alt="Italiano"></a>
    51     <a href="/?lang=nl&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=nl" title="Nederlands" alt="Nederlands"></a>
    52     <a href="/?lang=pl&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=pl" title="Polski" alt="Polski"></a>
    53     <a href="/?lang=pt&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=pt" title="Português" alt="Português"></a>
    54     <a href="/?lang=ru&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=ru" title="Русский" alt="Русский"></a>
    55     <a href="/?lang=sv&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=se" title="Svenska" alt="Svenska"></a>
    56     <a href="/?lang=uk&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=ua" title="Ukrainian" alt="Ukrainian"></a>
    57     <a href="/?lang=vi&amp;consoleNonce=<%=consoleNonce%>"><img height="11" width="16" style="padding: 0 2px;" src="/flags.jsp?c=vn" title="Tiếng Việt" alt="Tiếng Việt"></a>
    58   </div>
    59   <a name="top"></a>
    60   <h2><%=intl._("Welcome to I2P")%></h2>
    61  </div>
    62  <% java.io.File fpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getBaseDir(), "docs/readme.html"); %>
    63  <jsp:setProperty name="contenthelper" property="page" value="<%=fpath.getAbsolutePath()%>" />
    64  <jsp:setProperty name="contenthelper" property="maxLines" value="300" />
    65  <jsp:setProperty name="contenthelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
    66  <jsp:getProperty name="contenthelper" property="content" />
    67 </div></body></html>
  • apps/routerconsole/jsp/viewstat.jsp

    rf43b0be r2b81cee  
    4848        int height = -1;
    4949        int periodCount = -1;
     50        int end = 0;
    5051        String str = request.getParameter("width");
    5152        if (str != null) try { width = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
     
    5455        str = request.getParameter("periodCount");
    5556        if (str != null) try { periodCount = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
     57        str = request.getParameter("end");
     58        if (str != null) try { end = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
    5659        boolean hideLegend = Boolean.valueOf(""+request.getParameter("hideLegend")).booleanValue();
    5760        boolean hideGrid = Boolean.valueOf(""+request.getParameter("hideGrid")).booleanValue();
     
    6467            rendered = net.i2p.router.web.StatSummarizer.instance().renderRatePng(cout, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit);
    6568        else
    66             rendered = net.i2p.router.web.StatSummarizer.instance().renderPng(rate, cout, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit);
     69            rendered = net.i2p.router.web.StatSummarizer.instance().renderPng(rate, cout, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, end, showCredit);
    6770      }
    6871      if (rendered)
  • apps/sam/java/build.xml

    rf43b0be r2b81cee  
    7373                <attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
    7474                <attribute name="Implementation-Version" value="${full.version}" />
     75                <attribute name="Built-By" value="${build.built-by}" />
    7576                <attribute name="Build-Date" value="${build.timestamp}" />
    7677                <attribute name="Base-Revision" value="${workspace.version}" />
     
    8889                <attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
    8990                <attribute name="Implementation-Version" value="${full.version}" />
     91                <attribute name="Built-By" value="${build.built-by}" />
    9092                <attribute name="Build-Date" value="${build.timestamp}" />
    9193                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/streaming/java/build.xml

    rf43b0be r2b81cee  
    6565            <manifest>
    6666                <attribute name="Implementation-Version" value="${full.version}" />
     67                <attribute name="Built-By" value="${build.built-by}" />
    6768                <attribute name="Build-Date" value="${build.timestamp}" />
    6869                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java

    rf43b0be r2b81cee  
    162162            //}
    163163            if (locked_tooManyStreams()) {
    164                 if (_log.shouldLog(Log.WARN))
    165                     _log.warn("Refusing connection since we have exceeded our max of "
     164                _log.logAlways(Log.WARN, "Refusing connection since we have exceeded our max of "
    166165                              + _maxConcurrentStreams + " connections");
    167166                reject = true;
     
    234233            long remaining = expiration - _context.clock().now();
    235234            if (remaining <= 0) {
    236                 if (_log.shouldLog(Log.WARN))
    237                 _log.warn("Refusing to connect since we have exceeded our max of "
     235                _log.logAlways(Log.WARN, "Refusing to connect since we have exceeded our max of "
    238236                          + _maxConcurrentStreams + " connections");
    239237                _numWaiting--;
     
    244242                    // allow a full buffer of pending/waiting streams
    245243                    if (_numWaiting > _maxConcurrentStreams) {
    246                         if (_log.shouldLog(Log.WARN))
    247                             _log.warn("Refusing connection since we have exceeded our max of "
     244                        _log.logAlways(Log.WARN, "Refusing connection since we have exceeded our max of "
    248245                                      + _maxConcurrentStreams + " and there are " + _numWaiting
    249246                                      + " waiting already");
  • apps/susidns/src/build.xml

    rf43b0be r2b81cee  
    100100            <manifest>
    101101                <attribute name="Implementation-Version" value="${full.version}" />
     102                <attribute name="Built-By" value="${build.built-by}" />
    102103                <attribute name="Build-Date" value="${build.timestamp}" />
    103104                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/susidns/src/java/src/i2p/susi/dns/AddressBean.java

    rf43b0be r2b81cee  
    171171        }
    172172
     173        /** @since 0.9 */
     174        public String getB64()
     175        {
     176                byte[] dest = Base64.decode(destination);
     177                if (dest == null)
     178                        return "";
     179                return I2PAppContext.getGlobalContext().sha().calculateHash(dest).toBase64();
     180        }
     181
    173182        /** @since 0.8.7 */
    174183        public void setProperties(Properties p) {
  • apps/susidns/src/jsp/addressbook.jsp

    rf43b0be r2b81cee  
    4444<html>
    4545<head>
    46 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     46<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    4747<title>${book.book} <%=intl._("address book")%> - susidns</title>
    4848<link rel="stylesheet" type="text/css" href="css.css">
     
    160160<span class="addrhlpr"><a href="details?h=${addr.name}" title="<%=intl._("More information on this entry")%>"><%=intl._("details")%></a></span>
    161161</td>
    162 <td class="destinations"><textarea rows="1" style="height: 3em;" cols="40" wrap="off" readonly="readonly" name="dest_${addr.name}" >${addr.destination}</textarea></td>
     162<td class="destinations"><textarea rows="1" style="height:3em;" wrap="off" cols="40" readonly="readonly" name="dest_${addr.name}" >${addr.destination}</textarea></td>
    163163</tr>
    164164</c:forEach>
     
    192192<b><%=intl._("Host Name")%></b></td><td><input type="text" name="hostname" value="${book.hostname}" size="54">
    193193</td></tr><tr><td>
    194 <b><%=intl._("Destination")%></b></td><td><textarea name="destination" rows="1" style="height: 3em;" cols="70" wrap="off" spellcheck="false">${book.destination}</textarea>
     194<b><%=intl._("Destination")%></b></td><td><textarea name="destination" rows="1" style="height:3em" wrap="off" cols="70" spellcheck="false">${book.destination}</textarea>
    195195</td></tr></table>
    196196<p class="buttons">
  • apps/susidns/src/jsp/config.jsp

    rf43b0be r2b81cee  
    4040<html>
    4141<head>
    42 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     42<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    4343<title><%=intl._("configuration")%> - susidns</title>
    4444<link rel="stylesheet" type="text/css" href="css.css">
  • apps/susidns/src/jsp/details.jsp

    rf43b0be r2b81cee  
    3838<html>
    3939<head>
    40 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     40<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    4141<title>${book.book} <%=intl._("addressbook")%> - susidns</title>
    4242<link rel="stylesheet" type="text/css" href="css.css">
     
    9696<td><a href="http://<%=b32%>/"><%=b32%></a></td>
    9797</tr><tr class="list${book.trClass}">
     98<td><%=intl._("Base 64 Hash")%></td>
     99<td><%=addr.getB64()%></td>
     100</tr><tr class="list${book.trClass}">
    98101<td><%=intl._("Address Helper")%></td>
    99102<td><a href="http://<%=addr.getName()%>/?i2paddresshelper=<%=addr.getDestination()%>"><%=intl._("link")%></a></td>
     
    121124</tr><tr class="list${book.trClass}">
    122125<td><%=intl._("Destination")%></td>
    123 <td class="destinations"><textarea rows="1" style="height: 3em;" cols="70" wrap="off" readonly="readonly" ><%=addr.getDestination()%></textarea></td>
     126<td class="destinations"><textarea rows="1" style="height:3em;" wrap="off" cols="70" readonly="readonly" ><%=addr.getDestination()%></textarea></td>
    124127</tr></table>
    125128</div>
  • apps/susidns/src/jsp/subscriptions.jsp

    rf43b0be r2b81cee  
    4040<html>
    4141<head>
    42 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     42<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    4343<title><%=intl._("subscriptions")%> - susidns</title>
    4444<link rel="stylesheet" type="text/css" href="css.css">
  • apps/susimail/build.xml

    rf43b0be r2b81cee  
    4848            <manifest>
    4949                <attribute name="Implementation-Version" value="${full.version}" />
     50                <attribute name="Built-By" value="${build.built-by}" />
    5051                <attribute name="Build-Date" value="${build.timestamp}" />
    5152                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/susimail/src/src/i2p/susi/webmail/WebMail.java

    rf43b0be r2b81cee  
    16561656                                        ", clear=" + sessionObject.clear );
    16571657                        out.println( "<tr class=\"list" + bg + "\"><td><input type=\"checkbox\" class=\"optbox\" name=\"check" + i + "\" value=\"1\"" +
    1658                                         ( idChecked ? "checked" : "" ) + ">" + ( RELEASE ? "" : "" + i ) + "</td><td>" + link + mail.shortSender + "</a></td><td>&nbsp;</td><td>" + link + mail.shortSubject + "</a></td><td>&nbsp;</td><td>" + mail.formattedDate + "</a></td><td>&nbsp;</td><td>" + ngettext("1 Byte", "{0} Bytes", mail.size) + "</a></td></tr>" );
     1658                                        ( idChecked ? "checked" : "" ) + ">" + ( RELEASE ? "" : "" + i ) + "</td><td>" + link + mail.shortSender + "</a></td><td>&nbsp;</td><td>" + link + mail.shortSubject + "</a></td><td>&nbsp;</td><td>" + mail.formattedDate + "</td><td>&nbsp;</td><td>" + ngettext("1 Byte", "{0} Bytes", mail.size) + "</td></tr>" );
    16591659                        bg = 1 - bg;
    16601660                        i++;
  • apps/systray/java/build.xml

    rf43b0be r2b81cee  
    4646                <attribute name="Class-Path" value="systray4j.jar" />
    4747                <attribute name="Implementation-Version" value="${full.version}" />
     48                <attribute name="Built-By" value="${build.built-by}" />
    4849                <attribute name="Build-Date" value="${build.timestamp}" />
    4950                <attribute name="Base-Revision" value="${workspace.version}" />
  • build.properties

    rf43b0be r2b81cee  
    1717i2pdocs.url=http://docs.i2p-projekt.de/javadoc/
    1818junitdocs.url=http://junit.org/apidocs/
     19# This will go in the jar manifests
     20build.built-by=unknown 
  • build.xml

    rf43b0be r2b81cee  
    170170                        excludes="org/jrobin/cmd/ org/jrobin/convertor/ org/jrobin/inspector/" />
    171171            <manifest>
     172                <attribute name="Built-By" value="${build.built-by}" />
    172173                <attribute name="Build-Date" value="${build.timestamp}" />
    173174                <attribute name="Base-Revision" value="${workspace.version}" />
     
    207208    </target>
    208209
     210    <!-- this makes an empty build/launchi2p.jar and the build/i2p.exe for the no-wrapper windows startup, if possible -->
    209211    <target name="buildexe">
    210212        <condition property="noExe">
     
    235237             classpath="${basedir}/installer/lib/launch4j/launch4j.jar:${basedir}/installer/lib/launch4j/lib/xstream.jar" />
    236238
     239    <!-- this makes an empty build/launchi2p.jar and the build/i2p.exe for the no-wrapper windows startup -->
    237240    <target name="doBuildEXE" depends="buildProperties" unless="noExe">
    238241        <jar destfile="./build/launchi2p.jar">
     
    240243             <attribute name="Main-Class" value="net.i2p.router.RouterLaunch" />
    241244             <attribute name="Class-Path" value="lib/i2p.jar lib/router.jar lib/jbigi.jar lib/BOB.jar lib/sam.jar lib/mstreaming.jar lib/streaming.jar lib/routerconsole.jar lib/i2ptunnel.jar lib/org.mortbay.jetty.jar lib/javax.servlet.jar lib/jasper-compiler.jar lib/jasper-runtime.jar lib/commons-logging.jar lib/commons-el.jar lib/wrapper.jar lib/systray.jar lib/systray4j.jar lib/desktopgui.jar" />
     245             <attribute name="Built-By" value="${build.built-by}" />
    242246             <attribute name="Build-Date" value="${build.timestamp}" />
    243247             <attribute name="Base-Revision" value="${workspace.version}" />
     
    290294            <fileset dir="installer/lib/jbigi" includes="*.so *.dll *.jnilib" />
    291295            <manifest>
     296                <attribute name="Built-By" value="${build.built-by}" />
    292297                <attribute name="Build-Date" value="${build.timestamp}" />
    293298                <attribute name="Base-Revision" value="${workspace.version}" />
     
    303308            <fileset dir="installer/lib/jbigi" includes="*.so *.jnilib" />
    304309            <manifest>
     310                <attribute name="Built-By" value="${build.built-by}" />
    305311                <attribute name="Build-Date" value="${build.timestamp}" />
    306312                <attribute name="Base-Revision" value="${workspace.version}" />
     
    317323            <fileset dir="installer/lib/jbigi" includes="*freebsd*.so" />
    318324            <manifest>
     325                <attribute name="Built-By" value="${build.built-by}" />
    319326                <attribute name="Build-Date" value="${build.timestamp}" />
    320327                <attribute name="Base-Revision" value="${workspace.version}" />
     
    330337            <fileset dir="installer/lib/jbigi" includes="*linux*.so" />
    331338            <manifest>
     339                <attribute name="Built-By" value="${build.built-by}" />
    332340                <attribute name="Build-Date" value="${build.timestamp}" />
    333341                <attribute name="Base-Revision" value="${workspace.version}" />
     
    343351            <fileset dir="installer/lib/jbigi" includes="*linux-arm*.so,*linux-ppc*.so" />
    344352            <manifest>
     353                <attribute name="Built-By" value="${build.built-by}" />
    345354                <attribute name="Build-Date" value="${build.timestamp}" />
    346355                <attribute name="Base-Revision" value="${workspace.version}" />
     
    356365            <fileset dir="installer/lib/jbigi" includes="*.jnilib" />
    357366            <manifest>
     367                <attribute name="Built-By" value="${build.built-by}" />
    358368                <attribute name="Build-Date" value="${build.timestamp}" />
    359369                <attribute name="Base-Revision" value="${workspace.version}" />
     
    369379            <fileset dir="installer/lib/jbigi" includes="*windows*.dll" />
    370380            <manifest>
     381                <attribute name="Built-By" value="${build.built-by}" />
    371382                <attribute name="Build-Date" value="${build.timestamp}" />
    372383                <attribute name="Base-Revision" value="${workspace.version}" />
     
    552563
    553564    <target name="verifyReleaseBuildNumbers" depends="getReleaseNumber, getBuildNumber" >
     565        <echo message="SDK: ${java.vendor} ${java.version} (${java.runtime.name} ${java.runtime.version})" />
    554566        <fail message="Bad release number: ${release.number}" >
    555567            <condition>
     
    580592        <delete file="installer/lib/izpack/patches.jar" failonerror="false" quiet="true" />     
    581593        <delete file="i2pinstall.exe" failonerror="false" quiet="true" />       
    582         <delete file="i2p.exe" failonerror="false" quiet="true" />
    583594        <delete file="syndie-standalone.zip" failonerror="false" quiet="true" />
    584595        <delete>
     
    771782   
    772783    <target name="preppkg-windows" depends="preppkg-base, buildexe">
    773         <copy file="i2p.exe" todir="pkg-temp/" failonerror="false" />
     784        <copy file="build/i2p.exe" todir="pkg-temp/" failonerror="false" />
    774785        <copy file="apps/systray/java/lib/systray4j.dll" todir="pkg-temp/lib" />
    775786        <copy file="apps/systray/java/resources/iggy.ico" todir="pkg-temp/icons" />
     
    936947
    937948    <target name="updater200" depends="prepupdate, preplicenses, pack200, zipit200" />
     949    <target name="updater200WithJetty" depends="prepjupdate, preplicenses, pack200, zipit200" />
    938950    <target name="updater200WithJettyFixes" depends="prepjupdatefixes, preplicenses, pack200, zipit200" />
    939951    <target name="updater200WithJettyFixesAndJbigi" depends="prepjupdatefixes, prepjbigiupdate, preplicenses, pack200, zipit200" />
     
    10261038        <!-- include systray changes in 0.7.5 -->
    10271039        <copy file="build/systray.jar" todir="pkg-temp/lib/" />
     1040       <!-- removed from updater in 0.9
    10281041        <copy file="build/desktopgui.jar" todir="pkg-temp/lib/" />
     1042       -->
    10291043        <copy file="build/susimail.war" todir="pkg-temp/webapps/" />
    10301044        <copy file="build/susidns.war" todir="pkg-temp/webapps/" />
     
    11361150            <manifest>
    11371151                <attribute name="Main-Class" value="net.i2p.util.Copy" />
     1152                <attribute name="Built-By" value="${build.built-by}" />
    11381153                <attribute name="Build-Date" value="${build.timestamp}" />
    11391154                <attribute name="Base-Revision" value="${workspace.version}" />
     
    11441159            <manifest>
    11451160                <attribute name="Main-Class" value="net.i2p.util.Delete" />
     1161                <attribute name="Built-By" value="${build.built-by}" />
    11461162                <attribute name="Build-Date" value="${build.timestamp}" />
    11471163                <attribute name="Base-Revision" value="${workspace.version}" />
     
    11521168            <manifest>
    11531169                <attribute name="Main-Class" value="net.i2p.util.Exec" />
     1170                <attribute name="Built-By" value="${build.built-by}" />
    11541171                <attribute name="Build-Date" value="${build.timestamp}" />
    11551172                <attribute name="Base-Revision" value="${workspace.version}" />
     
    11891206    </target>
    11901207
     1208    <!-- this makes i2pinstall.exe from install.jar -->
    11911209    <target name="doInstallerEXE" unless="noExe">
    11921210        <!-- now the installer exe -->
    11931211        <launch4j configFile="./installer/i2pinstaller.xml" />
    1194         <launch4j configFile="./installer/i2pstandalone.xml" />
    11951212        <!-- thazzit -->
    11961213    </target>
    11971214
    11981215    <!-- Custom installers -->
    1199     <target name="installer-nowindows" depends="clean, preppkg-nowindows, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
    1200         <mkdir dir="pkg-temp/installer" />
    1201         <!-- set if unset -->
    1202         <property name="workspace.changes.util.tr" value="" />
    1203         <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}.jar" installerType="standard" basedir="${basedir}" />
    1204     </target>
    1205 
    1206 
    1207     <target name="installer-freebsd" depends="clean, preppkg-freebsd-only, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
    1208         <mkdir dir="pkg-temp/installer" />
    1209         <!-- set if unset -->
    1210         <property name="workspace.changes.util.tr" value="" />
    1211         <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_freebsd-only.jar" installerType="standard" basedir="${basedir}" />
    1212     </target>
    1213 
    1214     <target name="installer-linux" depends="clean, preppkg-linux-only, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
    1215         <mkdir dir="pkg-temp/installer" />
    1216         <!-- set if unset -->
    1217         <property name="workspace.changes.util.tr" value="" />
    1218         <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_linux-only.jar" installerType="standard" basedir="${basedir}" />
    1219     </target>
    1220 
    1221 
    1222     <target name="installer-osx" depends="clean, checkForIzpack2App, preppkg-osx-only, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches">
    1223         <mkdir dir="pkg-temp/installer" />
     1216    <target name="installer-nowindows" depends="clean, preppkg-nowindows, izpack-patches" >
     1217        <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}.jar" installerType="standard" basedir="${basedir}" />
     1218    </target>
     1219
     1220
     1221    <target name="installer-freebsd" depends="clean, preppkg-freebsd-only, izpack-patches" >
     1222        <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_freebsd-only.jar" installerType="standard" basedir="${basedir}" />
     1223    </target>
     1224
     1225    <target name="installer-linux" depends="clean, preppkg-linux-only, izpack-patches" >
     1226        <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_linux-only.jar" installerType="standard" basedir="${basedir}" />
     1227    </target>
     1228
     1229
     1230    <target name="installer-osx" depends="clean, checkForIzpack2App, preppkg-osx-only, izpack-patches">
    12241231        <mkdir dir="pkg-temp/osx" />
    1225         <!-- set if unset -->
    1226         <property name="workspace.changes.util.tr" value="" />
    1227         <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_osx-only.jar" installerType="standard" basedir="${basedir}" />
     1232        <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_osx-only.jar" installerType="standard" basedir="${basedir}" />
    12281233        <ant target="installer2app" />
    12291234        <delete dir="pkg-temp/osx" />
     
    12381243        <exec executable="python" failonerror="true">
    12391244            <arg value="${user.home}/IzPack/utils/wrappers/izpack2app/izpack2app.py" />
    1240             <arg value="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_osx-only.jar" />
    1241             <arg value="${basedir}/pkg-temp/osx/i2p-${release.number}-${i2p.build.number}${build.extra}_osx-install.app" />
     1245            <arg value="${basedir}/i2pinstall_${full.version}_osx-only.jar" />
     1246            <arg value="${basedir}/pkg-temp/osx/i2p-${full.version}_osx-install.app" />
    12421247        </exec>
    12431248        <exec executable="chmod" failonerror="true" osfamily="unix">
    12441249                <arg value="755" />
    1245                 <arg value="${basedir}/pkg-temp/osx/i2p-${release.number}-${i2p.build.number}${build.extra}_osx-install.app/Contents/MacOS/JavaApplicationStub" />
     1250                <arg value="${basedir}/pkg-temp/osx/i2p-${full.version}_osx-install.app/Contents/MacOS/JavaApplicationStub" />
    12461251        </exec>
    12471252        <exec executable="tar" osfamily="unix" failonerror="true">
     
    12491254                <arg value="--group=root" />
    12501255                <arg value="-cjvf" />
    1251                 <arg value="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_osx.tar.bz2" />
     1256                <arg value="${basedir}/i2pinstall_${full.version}_osx.tar.bz2" />
    12521257                <arg value="-C" />
    12531258                <arg value="${basedir}/pkg-temp/osx" />
    1254                 <arg value="i2p-${release.number}-${i2p.build.number}${build.extra}_osx-install.app" />
     1259                <arg value="i2p-${full.version}_osx-install.app" />
    12551260        </exec>
    12561261    </target>
    12571262
    1258     <!-- Yes, even though this makes an installer for Windows, we still need to depend on preppkg-unix (because the installer attempts to delete these files
    1259      and will fail if they don't exist. Thankfully these files are so very small there's not much harm in including them.
    1260     -->
    1261     <target name="installer-windows" depends="clean, doBuildEXE, preppkg-windows-only, preppkg-unix, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
     1263    <target name="installer-windows" depends="clean, preppkg-windows-only, util-list-changes, izpack-patches" >
    12621264        <mkdir dir="pkg-temp/installer" />
    12631265        <!-- set if unset -->
     
    12661268            <manifest>
    12671269                <attribute name="Main-Class" value="net.i2p.util.Copy" />
     1270                <attribute name="Built-By" value="${build.built-by}" />
    12681271                <attribute name="Build-Date" value="${build.timestamp}" />
    12691272                <attribute name="Base-Revision" value="${workspace.version}" />
     
    12741277            <manifest>
    12751278                <attribute name="Main-Class" value="net.i2p.util.Delete" />
     1279                <attribute name="Built-By" value="${build.built-by}" />
    12761280                <attribute name="Build-Date" value="${build.timestamp}" />
    12771281                <attribute name="Base-Revision" value="${workspace.version}" />
     
    12821286            <manifest>
    12831287                <attribute name="Main-Class" value="net.i2p.util.Exec" />
     1288                <attribute name="Built-By" value="${build.built-by}" />
    12841289                <attribute name="Build-Date" value="${build.timestamp}" />
    12851290                <attribute name="Base-Revision" value="${workspace.version}" />
     
    12871292            </manifest>
    12881293        </jar>
    1289         <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_windows-only.jar" installerType="standard" basedir="${basedir}" />
    1290         <delete dir="pkg-temp/win" />
     1294        <izpack input="${basedir}/installer/install.xml" output="${basedir}/install.jar" installerType="standard" basedir="${basedir}" />
     1295        <ant target="installerexe" />
     1296        <delete file="${basedir}/install.jar" />
     1297        <move file="${basedir}/i2pinstall.exe" tofile="${basedir}/i2pinstall_${full.version}_windows-only.exe" />
    12911298    </target>
    12921299
     
    14031410        <copy file="i2pupdate.zip" tofile="i2pupdate_${release.number}.zip" />
    14041411        <copy file="i2pinstall.exe" tofile="i2pinstall_${release.number}.exe" />
    1405         <delete file="i2pupdate.sud" failonerror="false" />
    1406         <delete file="i2pupdate.su2" failonerror="false" />
     1412        <delete file="i2pupdate.sud" />
     1413        <delete file="i2pupdate.su2" />
     1414        <!-- make this a lot easier by putting release.privkey=/path/to/privkey in override.properties -->
    14071415        <input message="Enter private signing key file:" addproperty="release.privkey" />
    14081416        <fail message="You must enter a path." >
     
    15141522            <arg value="i2pupdate_${release.number}.zip" />
    15151523        </exec>
     1524        <exec executable="chmod" failonerror="true">
     1525            <arg value="444" />
     1526            <arg value="i2pinstall_${release.number}.exe" />
     1527            <arg value="i2psource_${release.number}.tar.bz2" />
     1528            <arg value="i2pupdate_${release.number}.zip" />
     1529            <arg value="i2pupdate.su2" />
     1530            <arg value="i2pupdate.sud" />
     1531            <arg value="i2pinstall_${release.number}.exe.sig" />
     1532            <arg value="i2psource_${release.number}.tar.bz2.sig" />
     1533            <arg value="i2pupdate_${release.number}.zip.sig" />
     1534        </exec>
    15161535        <echo message="File sizes:" />
    15171536        <exec executable="ls" failonerror="true">
  • core/java/build.xml

    rf43b0be r2b81cee  
    6060            <manifest>
    6161                <attribute name="Implementation-Version" value="${full.version}" />
     62                <attribute name="Built-By" value="${build.built-by}" />
    6263                <attribute name="Build-Date" value="${build.timestamp}" />
    6364                <attribute name="Base-Revision" value="${workspace.version}" />
  • core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java

    rf43b0be r2b81cee  
    3535 */
    3636class RequestLeaseSetMessageHandler extends HandlerImpl {
    37     private final Map _existingLeaseSets;
     37    private final Map<Destination, LeaseInfo> _existingLeaseSets;
    3838
    3939    public RequestLeaseSetMessageHandler(I2PAppContext context) {
     
    6060
    6161        // reuse the old keys for the client
    62         LeaseInfo li = (LeaseInfo) _existingLeaseSets.get(session.getMyDestination());
     62        LeaseInfo li = _existingLeaseSets.get(session.getMyDestination());
    6363        if (li == null) {
    6464            li = new LeaseInfo(session.getMyDestination());
     
    9999
    100100    private static class LeaseInfo {
    101         private PublicKey _pubKey;
    102         private PrivateKey _privKey;
    103         private SigningPublicKey _signingPubKey;
    104         private SigningPrivateKey _signingPrivKey;
    105         private Destination _dest;
     101        private final PublicKey _pubKey;
     102        private final PrivateKey _privKey;
     103        private final SigningPublicKey _signingPubKey;
     104        private final SigningPrivateKey _signingPrivKey;
     105        private final Destination _dest;
    106106
    107107        public LeaseInfo(Destination dest) {
  • core/java/src/net/i2p/client/naming/BlockfileNamingService.java

    rf43b0be r2b81cee  
    9393    private final List<String> _lists;
    9494    private final List<InvalidEntry> _invalid;
     95    private final Map<String, String> _negativeCache;
    9596    private volatile boolean _isClosed;
    9697    private final boolean _readOnly;
     
    119120    private static final String PROP_SOURCE = "s";
    120121   
     122    private static final String DUMMY = "";
     123    private static final int NEGATIVE_CACHE_SIZE = 32;
     124
    121125    /**
    122126     *  Opens the database at hostsdb.blockfile or creates a new
     
    133137        _lists = new ArrayList();
    134138        _invalid = new ArrayList();
     139        _negativeCache = new LHM(NEGATIVE_CACHE_SIZE);
    135140        BlockFile bf = null;
    136141        RAIFile raf = null;
     
    629634
    630635        String key = hostname.toLowerCase(Locale.US);
     636        synchronized(_negativeCache) {
     637            if (_negativeCache.get(key) != null)
     638                return null;
     639        }
    631640        synchronized(_bf) {
    632641            if (_isClosed)
     
    651660            deleteInvalid();
    652661        }
    653         if (d != null)
     662        if (d != null) {
    654663            putCache(hostname, d);
     664        } else {
     665            synchronized(_negativeCache) {
     666                _negativeCache.put(key, DUMMY);
     667            }
     668        }
    655669        return d;
    656670    }
     
    684698        }
    685699        String key = hostname.toLowerCase(Locale.US);
     700        synchronized(_negativeCache) {
     701            _negativeCache.remove(key);
     702        }
    686703        String listname = FALLBACK_LIST;
    687704        Properties props = new Properties();
     
    10321049            _isClosed = true;
    10331050        }
     1051        synchronized(_negativeCache) {
     1052            _negativeCache.clear();
     1053        }
    10341054        clearCache();
    10351055    }
  • core/java/src/net/i2p/client/naming/DummyNamingService.java

    rf43b0be r2b81cee  
    117117    }
    118118
    119     private static class LHM<K, V> extends LinkedHashMap<K, V> {
     119    protected static class LHM<K, V> extends LinkedHashMap<K, V> {
    120120        private final int _max;
    121121
  • core/java/src/net/i2p/crypto/TransientSessionKeyManager.java

    rf43b0be r2b81cee  
    626626            Set<TagSet> sets = new TreeSet(new TagSetComparator());
    627627            sets.addAll(sess.getTagSets());
    628             buf.append("<tr><td><b>Target key:</b> ").append(sess.getTarget().toBase64().substring(0, 64)).append("<br>" +
     628            buf.append("<tr><td><b>Target public key:</b> ").append(sess.getTarget().toBase64().substring(0, 20)).append("...<br>" +
    629629                       "<b>Established:</b> ").append(DataHelper.formatDuration(now - sess.getEstablishedDate())).append(" ago<br>" +
    630630                       "<b>Last Used:</b> ").append(DataHelper.formatDuration(now - sess.getLastUsedDate())).append(" ago<br>" +
  • core/java/src/net/i2p/data/Base32.java

    rf43b0be r2b81cee  
    3030public class Base32 {
    3131
    32     private final static Log _log = new Log(Base32.class);
     32    //private final static Log _log = new Log(Base32.class);
    3333
    3434    /** The 32 valid Base32 values. */
     
    249249                         usedbits -= 3;
    250250                     } else if (next != 0) {
    251                        _log.warn("Extra data at the end: " + next + "(decimal)");
     251                       //_log.warn("Extra data at the end: " + next + "(decimal)");
    252252                       return null;
    253253                     }
    254254                 }
    255255            } else {
    256                 _log.warn("Bad Base32 input character at " + i + ": " + source[i] + "(decimal)");
     256                //_log.warn("Bad Base32 input character at " + i + ": " + source[i] + "(decimal)");
    257257                return null;
    258258            }
  • core/java/src/net/i2p/data/Base64.java

    rf43b0be r2b81cee  
    4242public class Base64 {
    4343
    44     private final static Log _log = new Log(Base64.class);
     44    //private final static Log _log = new Log(Base64.class);
    4545
    4646    /**
     
    751751            } // end if: white space, equals sign or better
    752752            else {
    753                 _log.warn("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
     753                //_log.warn("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
    754754                return null;
    755755            } // end else:
  • core/java/src/net/i2p/data/DataHelper.java

    rf43b0be r2b81cee  
    13001300        //}
    13011301        ArrayList<DataStructure> rv = new ArrayList(dataStructures);
    1302         Collections.sort(rv, new DataStructureComparator());
     1302        sortStructureList(rv);
    13031303        return rv;
     1304    }
     1305
     1306    /**
     1307     *  See above.
     1308     *  DEPRECATED - Only used by RouterInfo.
     1309     *
     1310     *  @since 0.9
     1311     */
     1312    static void sortStructureList(List<? extends DataStructure> dataStructures) {
     1313        Collections.sort(dataStructures, new DataStructureComparator());
    13041314    }
    13051315
  • core/java/src/net/i2p/data/DataStructureImpl.java

    rf43b0be r2b81cee  
    1515import java.io.InputStream;
    1616
     17import net.i2p.I2PAppContext;
    1718import net.i2p.crypto.SHA256Generator;
    1819import net.i2p.util.Log;
     
    2425 */
    2526public abstract class DataStructureImpl implements DataStructure {
    26     private final static Log _log = new Log(DataStructureImpl.class);
    2727   
    2828    public String toBase64() {
     
    4949            return baos.toByteArray();
    5050        } catch (IOException ioe) {
    51             _log.error("Error writing out the byte array", ioe);
     51            Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
     52            log.error("Error writing out the byte array", ioe);
    5253            return null;
    5354        } catch (DataFormatException dfe) {
    54             _log.error("Error writing out the byte array", dfe);
     55            Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
     56            log.error("Error writing out the byte array", dfe);
    5557            return null;
    5658        }
  • core/java/src/net/i2p/data/Lease.java

    rf43b0be r2b81cee  
    2727    private TunnelId _tunnelId;
    2828    private Date _end;
    29     private int _numSuccess;
    30     private int _numFailure;
     29    //private int _numSuccess;
     30    //private int _numFailure;
    3131
    3232    public Lease() {
     
    7575     * @deprecated unused
    7676     */
     77/****
    7778    public int getNumSuccess() {
    7879        return _numSuccess;
    7980    }
     81****/
    8082
    8183    /** @deprecated unused */
     84/****
    8285    public void setNumSuccess(int num) {
    8386        _numSuccess = num;
    8487    }
     88****/
    8589
    8690    /**
     
    9094     * @deprecated unused
    9195     */
     96/****
    9297    public int getNumFailure() {
    9398        return _numFailure;
    9499    }
     100****/
    95101
    96102    /** @deprecated unused */
     103/****
    97104    public void setNumFailure(int num) {
    98105        _numFailure = num;
    99106    }
     107****/
    100108
    101109    /** has this lease already expired? */
  • core/java/src/net/i2p/data/LeaseSet.java

    rf43b0be r2b81cee  
    5757 */
    5858public class LeaseSet extends DatabaseEntry {
    59     private final static Log _log = new Log(LeaseSet.class);
    6059    private Destination _destination;
    6160    private PublicKey _encryptionKey;
     
    7271    private boolean _checked;
    7372
    74     /** This seems like plenty  */
    75     public final static int MAX_LEASES = 6;
     73    /**
     74     *  Unlimited before 0.6.3;
     75     *  6 as of 0.6.3;
     76     *  Increased in version 0.9.
     77     *
     78     *  Leasesets larger than 6 should be used with caution,
     79     *  as each lease adds 44 bytes, and routers older than version 0.9
     80     *  will not be able to connect as they will throw an exception in
     81     *  readBytes(). Also, the churn will be quite rapid, leading to
     82     *  frequent netdb stores and transmission on existing connections.
     83     *
     84     *  However we increase it now in case some hugely popular eepsite arrives.
     85     *  Strategies elsewhere in the router to efficiently handle
     86     *  large leasesets are TBD.
     87     */
     88    public static final int MAX_LEASES = 16;
     89    private static final int OLD_MAX_LEASES = 6;
    7690
    7791    public LeaseSet() {
    78         _leases = new ArrayList(MAX_LEASES);
     92        _leases = new ArrayList(OLD_MAX_LEASES);
    7993        _firstExpiration = Long.MAX_VALUE;
    8094    }
     
    355369     */
    356370    public void encrypt(SessionKey key) {
    357         if (_log.shouldLog(Log.WARN))
    358             _log.warn("encrypting lease: " + _destination.calculateHash());
     371        //if (_log.shouldLog(Log.WARN))
     372        //    _log.warn("encrypting lease: " + _destination.calculateHash());
    359373        try {
    360374            encryp(key);
    361375        } catch (DataFormatException dfe) {
    362             _log.error("Error encrypting lease: " + _destination.calculateHash());
     376            Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class);
     377            log.error("Error encrypting lease: " + _destination.calculateHash());
    363378        } catch (IOException ioe) {
    364             _log.error("Error encrypting lease: " + _destination.calculateHash());
     379            Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class);
     380            log.error("Error encrypting lease: " + _destination.calculateHash());
    365381        }
    366382    }
     
    421437     */
    422438    private void decrypt(SessionKey key) throws DataFormatException, IOException {
    423         if (_log.shouldLog(Log.WARN))
    424             _log.warn("decrypting lease: " + _destination.calculateHash());
     439        //if (_log.shouldLog(Log.WARN))
     440        //    _log.warn("decrypting lease: " + _destination.calculateHash());
    425441        int size = _leases.size();
    426442        if (size < 2)
     
    469485                _decrypted = true;
    470486            } catch (DataFormatException dfe) {
    471                 _log.error("Error decrypting lease: " + _destination.calculateHash() + dfe);
     487                Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class);
     488                log.error("Error decrypting lease: " + _destination.calculateHash() + dfe);
    472489            } catch (IOException ioe) {
    473                 _log.error("Error decrypting lease: " + _destination.calculateHash() + ioe);
     490                Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class);
     491                log.error("Error decrypting lease: " + _destination.calculateHash() + ioe);
    474492            }
    475493        }
  • core/java/src/net/i2p/data/Payload.java

    rf43b0be r2b81cee  
    2727 */
    2828public class Payload extends DataStructureImpl {
    29     private final static Log _log = new Log(Payload.class);
     29    //private final static Log _log = new Log(Payload.class);
    3030    private byte[] _encryptedData;
    3131    private byte[] _unencryptedData;
     
    8383        int read = read(in, _encryptedData);
    8484        if (read != size) throw new DataFormatException("Incorrect number of bytes read in the payload structure");
    85         if (_log.shouldLog(Log.DEBUG))
    86             _log.debug("read payload: " + read + " bytes");
     85        //if (_log.shouldLog(Log.DEBUG))
     86        //    _log.debug("read payload: " + read + " bytes");
    8787    }
    8888   
     
    9191        DataHelper.writeLong(out, 4, _encryptedData.length);
    9292        out.write(_encryptedData);
    93         if (_log.shouldLog(Log.DEBUG))
    94             _log.debug("wrote payload: " + _encryptedData.length);
     93        //if (_log.shouldLog(Log.DEBUG))
     94        //    _log.debug("wrote payload: " + _encryptedData.length);
    9595    }
    9696
  • core/java/src/net/i2p/data/RouterInfo.java

    rf43b0be r2b81cee  
    1414import java.io.InputStream;
    1515import java.io.OutputStream;
     16import java.util.ArrayList;
    1617import java.util.Collection;
    1718import java.util.Collections;
     
    2526import java.util.Vector;
    2627
     28import net.i2p.I2PAppContext;
    2729import net.i2p.crypto.SHA256Generator;
    2830import net.i2p.util.Clock;
     
    4446 */
    4547public class RouterInfo extends DatabaseEntry {
    46     private final static Log _log = new Log(RouterInfo.class);
    4748    private RouterIdentity _identity;
    4849    private volatile long _published;
    49     private final Set<RouterAddress> _addresses;
     50    /**
     51     *  Addresses must be sorted by SHA256.
     52     *  When an RI is created, they are sorted in setAddresses().
     53     *  Save addresses in the order received so we need not resort.
     54     */
     55    private final List<RouterAddress> _addresses;
    5056    /** may be null to save memory, no longer final */
    5157    private Set<Hash> _peers;
     
    7278   
    7379    public RouterInfo() {
    74         _addresses = new HashSet(2);
     80        _addresses = new ArrayList(2);
    7581        _options = new OrderedProperties();
    7682    }
     
    157163     * @return unmodifiable view, non-null
    158164     */
    159     public Set<RouterAddress> getAddresses() {
    160             return Collections.unmodifiableSet(_addresses);
     165    public Collection<RouterAddress> getAddresses() {
     166            return Collections.unmodifiableCollection(_addresses);
    161167    }
    162168
     
    165171     * can be contacted.
    166172     *
    167      * @throws IllegalStateException if RouterInfo is already signed
    168      */
    169     public void setAddresses(Set<RouterAddress> addresses) {
    170         if (_signature != null)
    171             throw new IllegalStateException();
    172         _addresses.clear();
    173         if (addresses != null) _addresses.addAll(addresses);
     173     * Warning - Sorts the addresses here. Do not modify any address
     174     *           after calling this, as the sort order is based on the
     175     *           hash of the entire address structure.
     176     *
     177     * @param addresses may be null
     178     * @throws IllegalStateException if RouterInfo is already signed or addresses previously set
     179     */
     180    public void setAddresses(Collection<RouterAddress> addresses) {
     181        if (_signature != null || !_addresses.isEmpty())
     182            throw new IllegalStateException();
     183        if (addresses != null) {
     184            _addresses.addAll(addresses);
     185            if (_addresses.size() > 1) {
     186                // WARNING this sort algorithm cannot be changed, as it must be consistent
     187                // network-wide. The signature is not checked at readin time, but only
     188                // later, and the addresses are stored in a Set, not a List.
     189                DataHelper.sortStructureList(_addresses);
     190            }
     191        }
    174192    }
    175193
     
    271289            } else {
    272290                DataHelper.writeLong(out, 1, sz);
    273                 Collection<RouterAddress> addresses = _addresses;
    274                 if (sz > 1) {
    275                     // WARNING this sort algorithm cannot be changed, as it must be consistent
    276                     // network-wide. The signature is not checked at readin time, but only
    277                     // later, and the addresses are stored in a Set, not a List.
    278                     addresses = (Collection<RouterAddress>) DataHelper.sortStructures(addresses);
    279                 }
    280                 for (RouterAddress addr : addresses) {
     291                for (RouterAddress addr : _addresses) {
    281292                    addr.writeBytes(out);
    282293                }
     
    459470
    460471        if (!_isValid) {
     472            Log log = I2PAppContext.getGlobalContext().logManager().getLog(RouterInfo.class);
    461473            byte data[] = null;
    462474            try {
    463475                data = getBytes();
    464476            } catch (DataFormatException dfe) {
    465                 _log.error("Error validating", dfe);
     477                log.error("Error validating", dfe);
    466478                return;
    467479            }
    468             if (_log.shouldLog(Log.ERROR))
    469                 _log.error("Invalid [" + SHA256Generator.getInstance().calculateHash(data).toBase64()
    470                            + (_log.shouldLog(Log.WARN) ? ("]\n" + toString()) : ""),
     480            log.error("Invalid [" + SHA256Generator.getInstance().calculateHash(data).toBase64()
     481                           + (log.shouldLog(Log.WARN) ? ("]\n" + toString()) : ""),
    471482                           new Exception("Signature failed"));
    472483        }
  • core/java/src/net/i2p/util/Log.java

    rf43b0be r2b81cee  
    1717 * Wrapper class for whatever logging system I2P uses.  This class should be
    1818 * instantiated and kept as a variable for each class it is used by, ala:
    19  *  <code>private final static Log _log = new Log(MyClassName.class);</code>
     19 *  <code>private final Log _log = context.logManager().getLog(MyClassName.class);</code>
    2020 *
    2121 * If there is anything in here that doesn't make sense, turn off your computer
  • core/java/src/net/i2p/util/SimpleTimer2.java

    rf43b0be r2b81cee  
    3232    private static final int MAX_THREADS = 4;
    3333    private final I2PAppContext _context;
    34     private static Log _log; // static so TimedEvent can use it
    3534    private final ScheduledThreadPoolExecutor _executor;
    3635    private final String _name;
     
    4140    protected SimpleTimer2(String name) {
    4241        _context = I2PAppContext.getGlobalContext();
    43         _log = _context.logManager().getLog(SimpleTimer2.class);
    4442        _name = name;
    4543        _count = 0;
     
    8078        protected void afterExecute(Runnable r, Throwable t) {
    8179            super.afterExecute(r, t);
    82             if (t != null) // shoudn't happen, caught in RunnableEvent.run()
    83                 _log.log(Log.CRIT, "wtf, event borked: " + r, t);
     80            if (t != null) { // shoudn't happen, caught in RunnableEvent.run()
     81                Log log = I2PAppContext.getGlobalContext().logManager().getLog(SimpleTimer2.class);
     82                log.log(Log.CRIT, "wtf, event borked: " + r, t);
     83            }