Changeset b0a682f


Ignore:
Timestamp:
Mar 3, 2012 7:05:15 PM (8 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
f010b27
Parents:
f22ac28 (diff), e2acc9f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

propagate from branch 'i2p.i2p.zzz.homepage' (head 27c8ea684056ce34ea81acdfd18571776ca63641)

to branch 'i2p.i2p' (head 83f37b19742045fa42ed71a0abd8e90d080c2c05)

Files:
4 added
90 edited
18 moved

Legend:

Unmodified
Added
Removed
  • apps/addressbook/build.xml

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    6262                <attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.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}" />
     
    9697        <!-- set if unset -->
    9798        <property name="workspace.changes.tr" value="" />
    98         <war destfile="../i2psnark.war" webxml="../web.xml" basedir="../" includes="_icons/*" >
     99        <copy todir="build/icons/.icons" >
     100            <fileset dir="../icons/" />
     101        </copy>
     102        <war destfile="../i2psnark.war" webxml="../web.xml" >
    99103          <!-- include only the web stuff, as of 0.7.12 the router will add i2psnark.jar to the classpath for the war -->
    100104          <classes dir="./build/obj" includes="**/web/*.class" />
     105            <fileset dir="build/icons/" />
    101106            <manifest>
    102107                <attribute name="Implementation-Version" value="${full.version}" />
     108                <attribute name="Built-By" value="${build.built-by}" />
    103109                <attribute name="Build-Date" value="${build.timestamp}" />
    104110                <attribute name="Base-Revision" value="${workspace.version}" />
     
    110116    <target name="warUpToDate">
    111117        <uptodate property="war.uptodate" targetfile="../i2psnark.war" >
    112             <srcfiles dir= "." includes="build/obj/org/klomp/snark/web/*.class ../_icons/* ../web.xml" />
     118            <srcfiles dir= "." includes="build/obj/org/klomp/snark/web/*.class ../icons/* ../web.xml" />
    113119        </uptodate>
    114120    </target>
  • apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    103103    {
    104104        if (pathInContext == null || pathInContext.equals("/") || pathInContext.equals("/index.jsp") ||
    105             pathInContext.equals("/index.html") || pathInContext.startsWith("/_icons/"))
     105            pathInContext.equals("/index.html") || pathInContext.startsWith("/.icons/") ||
     106            pathInContext.startsWith("/.js/") || pathInContext.startsWith("/.ajax/"))
    106107            return super.getResource(pathInContext);
    107108        // files in the i2psnark/ directory
     
    152153        // this is the part after /i2psnark
    153154        String path = req.getServletPath();
     155
     156        // AJAX for mainsection
     157        if ("/.ajax/xhr1.html".equals(path)) {
     158            resp.setCharacterEncoding("UTF-8");
     159            resp.setContentType("text/html; charset=UTF-8");
     160            PrintWriter out = resp.getWriter();
     161            //if (_log.shouldLog(Log.DEBUG))
     162            //    _manager.addMessage((_context.clock().now() / 1000) + " xhr1 p=" + req.getParameter("p"));
     163            writeMessages(out);
     164            writeTorrents(out, req);
     165            return;
     166        }
     167
    154168        boolean isConfigure = "/configure".equals(path);
    155169        // index.jsp doesn't work, it is grabbed by the war handler before here
     
    193207        String peerParam = req.getParameter("p");
    194208        String peerString;
    195         if (peerParam == null || !_manager.util().connected()) {
     209        if (peerParam == null || (!_manager.util().connected()) ||
     210            peerParam.replaceAll("[a-zA-Z0-9~=-]", "").length() > 0) {  // XSS
    196211            peerString = "";
    197212        } else {
     
    209224                                         
    210225        // we want it to go to the base URI so we don't refresh with some funky action= value
     226        int delay = 0;
    211227        if (!isConfigure) {
    212             int delay = _manager.getRefreshDelaySeconds();
    213             if (delay > 0)
    214                 out.write("<meta http-equiv=\"refresh\" content=\"" + delay + ";/i2psnark/" + peerString + "\">\n");
    215         }
    216         out.write(HEADER_A + _themePath + HEADER_B);
    217         out.write("</head><body>");
     228            delay = _manager.getRefreshDelaySeconds();
     229            if (delay > 0) {
     230                //out.write("<meta http-equiv=\"refresh\" content=\"" + delay + ";/i2psnark/" + peerString + "\">\n");
     231                out.write("<script src=\"/js/ajax.js\" type=\"text/javascript\"></script>\n" +
     232                          "<script type=\"text/javascript\">\n"  +
     233                          "function requestAjax1() { ajax(\"/i2psnark/.ajax/xhr1.html" + peerString + "\", \"mainsection\", " + (delay*1000) + "); }\n" +
     234                          "function initAjax(delayMs) { setTimeout(requestAjax1, " + (delay*1000) +");  }\n"  +
     235                          "</script>\n");
     236            }
     237        }
     238        out.write(HEADER_A + _themePath + HEADER_B + "</head>\n");
     239        if (isConfigure || delay <= 0)
     240            out.write("<body>");
     241        else
     242            out.write("<body onload=\"initAjax()\">");
    218243        out.write("<center>");
    219244        if (isConfigure) {
     
    250275        if (newURL != null && newURL.trim().length() > 0 && req.getMethod().equals("GET"))
    251276            _manager.addMessage(_("Click \"Add torrent\" button to fetch torrent"));
    252         out.write("<div class=\"page\"><div class=\"mainsection\"><div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
     277        out.write("<div class=\"page\"><div id=\"mainsection\" class=\"mainsection\">");
     278
     279        writeMessages(out);
     280
     281        if (isConfigure) {
     282            // end of mainsection div
     283            out.write("<div class=\"logshim\"></div></div>\n");
     284            writeConfigForm(out, req);
     285            writeTrackerForm(out, req);
     286        } else {
     287            writeTorrents(out, req);
     288            // end of mainsection div
     289            out.write("</div><div id=\"lowersection\">\n");
     290            writeAddForm(out, req);
     291            writeSeedForm(out, req);
     292            writeConfigLink(out);
     293            // end of lowersection div
     294            out.write("</div>\n");
     295        }
     296        out.write(FOOTER);
     297    }
     298
     299    private void writeMessages(PrintWriter out) throws IOException {
     300        out.write("<div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
    253301        List msgs = _manager.getMessages();
    254302        for (int i = msgs.size()-1; i >= 0; i--) {
     
    257305        }
    258306        out.write("</pre></td></tr></table></div>");
    259 
    260         if (isConfigure) {
    261             out.write("<div class=\"logshim\"></div></div>\n");
    262             writeConfigForm(out, req);
    263         } else {
    264             writeTorrents(out, req);
    265             out.write("</div>\n");
    266             writeAddForm(out, req);
    267             writeSeedForm(out, req);
    268             writeConfigLink(out);
    269         }
    270         out.write(FOOTER);
    271307    }
    272308
     
    277313
    278314        List snarks = getSortedSnarks(req);
    279         String uri = req.getRequestURI();
    280315        boolean isForm = _manager.util().connected() || !snarks.isEmpty();
    281316        if (isForm) {
     
    391426        }
    392427        out.write("</th></tr></thead>\n");
     428        String uri = "/i2psnark/";
    393429        for (int i = 0; i < snarks.size(); i++) {
    394430            Snark snark = (Snark)snarks.get(i);
     
    651687                                  seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts,
    652688                                  upLimit, upBW, useOpenTrackers, openTrackers, theme);
     689        } else if ("Save2".equals(action)) {
     690            String taction = req.getParameter("taction");
     691            if (taction != null)
     692                processTrackerForm(taction, req);
    653693        } else if ("Create".equals(action)) {
    654694            String baseData = req.getParameter("baseFile");
     
    656696                File baseFile = new File(_manager.getDataDir(), baseData);
    657697                String announceURL = req.getParameter("announceURL");
    658                 String announceURLOther = req.getParameter("announceURLOther");
    659                 if ( (announceURLOther != null) && (announceURLOther.trim().length() > "http://.i2p/announce".length()) )
    660                     announceURL = announceURLOther;
     698                // make the user add a tracker on the config form now
     699                //String announceURLOther = req.getParameter("announceURLOther");
     700                //if ( (announceURLOther != null) && (announceURLOther.trim().length() > "http://.i2p/announce".length()) )
     701                //    announceURL = announceURLOther;
    661702
    662703                if (announceURL == null || announceURL.length() <= 0)
     
    669710                        // This may take a long time to check the storage, but since it already exists,
    670711                        // it shouldn't be THAT bad, so keep it in this thread.
    671                         Storage s = new Storage(_manager.util(), baseFile, announceURL, null);
     712                        Storage s = new Storage(_manager.util(), baseFile, announceURL, req.getParameter("private") != null, null);
    672713                        s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
    673714                        MetaInfo info = s.getMetaInfo();
     
    710751                    snark.startTorrent();
    711752            }
     753        } else {
     754            _manager.addMessage("Unknown POST action: \"" + action + '\"');
     755        }
     756    }
     757
     758    /** @since 0.9 */
     759    private void processTrackerForm(String action, HttpServletRequest req) {
     760        if (action.equals(_("Delete selected"))) {
     761            boolean changed = false;
     762            Map<String, String> trackers = _manager.getTrackers();
     763            Enumeration e = req.getParameterNames();
     764            while (e.hasMoreElements()) {
     765                 Object o = e.nextElement();
     766                 if (!(o instanceof String))
     767                     continue;
     768                 String k = (String) o;
     769                 if (!k.startsWith("delete_"))
     770                     continue;
     771                 k = k.substring(7);
     772                 if (trackers.remove(k) != null) {
     773                    _manager.addMessage(_("Removed") + ": " + k);
     774                    changed = true;
     775                }
     776            }
     777            if (changed) {
     778                _manager.saveTrackerMap();
     779            }
     780        } else if (action.equals(_("Add tracker"))) {
     781            String name = req.getParameter("tname");
     782            String hurl = req.getParameter("thurl");
     783            String aurl = req.getParameter("taurl");
     784            if (name != null && hurl != null && aurl != null) {
     785                name = name.trim();
     786                hurl = hurl.trim();
     787                aurl = aurl.trim().replace("=", "&#61;");
     788                if (name.length() > 0 && hurl.startsWith("http://") && aurl.startsWith("http://")) {
     789                    Map<String, String> trackers = _manager.getTrackers();
     790                    trackers.put(name, aurl + '=' + hurl);
     791                    _manager.saveTrackerMap();
     792                } else {
     793                    _manager.addMessage(_("Enter valid tracker name and URLs"));
     794                }
     795            } else {
     796                _manager.addMessage(_("Enter valid tracker name and URLs"));
     797            }
     798        } else if (action.equals(_("Restore defaults"))) {
     799            _manager.setDefaultTrackerMap();
     800            _manager.addMessage(_("Restored default trackers"));
    712801        } else {
    713802            _manager.addMessage("Unknown POST action: \"" + action + '\"');
     
    12231312        // not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve)
    12241313        //out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>");
    1225         out.write("<input type=\"submit\" value=\"");
     1314        out.write("<input type=\"submit\" class=\"add\" value=\"");
    12261315        out.write(_("Add torrent"));
    12271316        out.write("\" name=\"foo\" ><br>\n");
     
    12701359        out.write(_("Open trackers only"));
    12711360        out.write("</option>\n");
    1272         Map trackers = _manager.getTrackers();
    1273         for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
    1274             Map.Entry entry = (Map.Entry)iter.next();
    1275             String name = (String)entry.getKey();
    1276             String announceURL = (String)entry.getValue();
     1361        Map<String, String> trackers = _manager.getTrackers();
     1362        for (Map.Entry<String, String> entry : trackers.entrySet()) {
     1363            String name = entry.getKey();
     1364            String announceURL = entry.getValue();
    12771365            int e = announceURL.indexOf('=');
    12781366            if (e > 0)
    1279                 announceURL = announceURL.substring(0, e);
     1367                announceURL = announceURL.substring(0, e).replace("&#61;", "=");
    12801368            if (announceURL.equals(_lastAnnounceURL))
    12811369                announceURL += "\" selected=\"selected";
     
    12831371        }
    12841372        out.write("</select>\n");
    1285         out.write(_("or"));
    1286         out.write("&nbsp;<input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
    1287                   "title=\"");
    1288         out.write(_("Specify custom tracker announce URL"));
    1289         out.write("\" > " +
    1290                   "<input type=\"submit\" value=\"");
     1373        // make the user add a tracker on the config form now
     1374        //out.write(_("or"));
     1375        //out.write("&nbsp;<input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
     1376        //          "title=\"");
     1377        //out.write(_("Specify custom tracker announce URL"));
     1378        //out.write("\" > " +
     1379        out.write(" <input type=\"submit\" class=\"create\" value=\"");
    12911380        out.write(_("Create torrent"));
    1292         out.write("\" name=\"foo\" ></table>\n" +
     1381        out.write("\" name=\"foo\" >\n" +
     1382                  "</td></tr><tr><td>");
     1383        out.write(_("Private?"));
     1384        out.write(" </td><td> <input type=\"checkbox\" class=\"optbox\" name=\"private\" value=\"true\" title=\"");
     1385            out.write(_("Use for private trackers"));
     1386        out.write("\"");
     1387        if (req.getParameter("private") != null)
     1388            out.write(" checked");
     1389        out.write("></td></tr>" +
     1390                  "</table>\n" +
    12931391                  "</form></div></div>");       
    12941392    }
    12951393   
    1296     private static final int[] times = { 30, 60, 2*60, 5*60, 10*60, 30*60, -1 };
     1394    private static final int[] times = { 5, 15, 30, 60, 2*60, 5*60, 10*60, 30*60, -1 };
    12971395
    12981396    private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException {
     
    13571455            out.write("\"");
    13581456            if (times[i] == delay)
    1359                 out.write(" selected=\"true\"");
     1457                out.write(" selected=\"selected\"");
    13601458            out.write(">");
    13611459            if (times[i] > 0)
     
    13801478        out.write("Seed percentage: <select name=\"seedPct\" disabled=\"true\" >\n\t");
    13811479        if (seedPct <= 0)
    1382             out.write("<option value=\"0\" selected=\"true\">Unlimited</option>\n\t");
     1480            out.write("<option value=\"0\" selected=\"selected\">Unlimited</option>\n\t");
    13831481        else
    13841482            out.write("<option value=\"0\">Unlimited</option>\n\t");
    13851483        if (seedPct == 100)
    1386             out.write("<option value=\"100\" selected=\"true\">100%</option>\n\t");
     1484            out.write("<option value=\"100\" selected=\"selected\">100%</option>\n\t");
    13871485        else
    13881486            out.write("<option value=\"100\">100%</option>\n\t");
    13891487        if (seedPct == 150)
    1390             out.write("<option value=\"150\" selected=\"true\">150%</option>\n\t");
     1488            out.write("<option value=\"150\" selected=\"selected\">150%</option>\n\t");
    13911489        else
    13921490            out.write("<option value=\"150\">150%</option>\n\t");
     
    14741572    }
    14751573   
     1574    /** @since 0.9 */
     1575    private void writeTrackerForm(PrintWriter out, HttpServletRequest req) throws IOException {
     1576        StringBuilder buf = new StringBuilder(1024);
     1577        buf.append("<form action=\"/i2psnark/configure\" method=\"POST\">\n" +
     1578                  "<div class=\"configsectionpanel\"><div class=\"snarkConfig\">\n" +
     1579                  "<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n" +
     1580                  "<input type=\"hidden\" name=\"action\" value=\"Save2\" >\n" +
     1581                  "<span class=\"snarkConfigTitle\">" +
     1582                  "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
     1583        buf.append(_("Trackers"));
     1584        buf.append("</span><hr>\n"   +
     1585                   "<table><tr><th>")
     1586           //.append(_("Remove"))
     1587           .append("</th><th>")
     1588           .append(_("Name"))
     1589           .append("</th><th>")
     1590           .append(_("Website URL"))
     1591           .append("</th><th>")
     1592           .append(_("Announce URL"))
     1593           .append("</th></tr>\n");
     1594        Map<String, String> trackers = _manager.getTrackers();
     1595        for (Map.Entry<String, String> entry : trackers.entrySet()) {
     1596            String name = entry.getKey();
     1597            String announceURL = entry.getValue();
     1598            int e = announceURL.indexOf('=');
     1599            if (e <= 0)
     1600                continue;
     1601            String homeURL = announceURL.substring(e + 1);
     1602            announceURL = announceURL.substring(0, e).replace("&#61;", "=");
     1603            buf.append("<tr><td align=\"center\"><input type=\"checkbox\" class=\"optbox\" name=\"delete_")
     1604               .append(name).append("\">" +
     1605                       "</td><td align=\"left\">").append(name)
     1606               .append("</td><td align=\"left\">").append(urlify(homeURL, 35))
     1607               .append("</td><td align=\"left\">").append(urlify(announceURL, 35))
     1608               .append("</td></tr>\n");
     1609        }
     1610        buf.append("<tr><td align=\"center\"><b>")
     1611           .append(_("Add")).append(":</b></td>" +
     1612                   "<td align=\"left\"><input type=\"text\" size=\"16\" name=\"tname\"></td>" +
     1613                   "<td align=\"left\"><input type=\"text\" size=\"40\" name=\"thurl\"></td>" +
     1614                   "<td align=\"left\"><input type=\"text\" size=\"40\" name=\"taurl\"></td></tr>\n" +
     1615                   "<tr><td colspan=\"2\"></td><td colspan=\"2\" align=\"left\">\n" +
     1616                   "<input type=\"submit\" name=\"taction\" class=\"default\" value=\"").append(_("Add tracker")).append("\">\n" +
     1617                   "<input type=\"submit\" name=\"taction\" class=\"delete\" value=\"").append(_("Delete selected")).append("\">\n" +
     1618                   // "<input type=\"reset\" class=\"cancel\" value=\"").append(_("Cancel")).append("\">\n" +
     1619                   "<input type=\"submit\" name=\"taction\" class=\"reload\" value=\"").append(_("Restore defaults")).append("\">\n" +
     1620                   "<input type=\"submit\" name=\"taction\" class=\"add\" value=\"").append(_("Add tracker")).append("\">\n" +
     1621                   "</td></tr></table></div></div></form>\n");
     1622        out.write(buf.toString());
     1623    }
     1624
    14761625    private void writeConfigLink(PrintWriter out) throws IOException {
    14771626        out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n" +
     
    15751724            buf.append("<option value=\"").append(i).append("\" ");
    15761725            if (i == now)
    1577                 buf.append("selected=\"true\" ");
     1726                buf.append("selected=\"selected\" ");
    15781727            // constants to prevent tagging
    15791728            buf.append(">").append(ngettext(DUMMY1 + name, DUMMY0 + name + 's', i));
     
    16231772    /** @since 0.7.14 */
    16241773    private static String urlify(String s) {
     1774        return urlify(s, 100);
     1775    }
     1776   
     1777    /** @since 0.9 */
     1778    private static String urlify(String s, int max) {
    16251779        StringBuilder buf = new StringBuilder(256);
    16261780        // browsers seem to work without doing this but let's be strict
    16271781        String link = urlEncode(s);
    1628         buf.append("<a href=\"").append(link).append("\">").append(link).append("</a>");
     1782        String display;
     1783        if (s.length() <= max)
     1784            display = link;
     1785        else
     1786            display = urlEncode(s.substring(0, max)) + "&hellip;";
     1787        buf.append("<a href=\"").append(link).append("\">").append(display).append("</a>");
    16291788        return buf.toString();
    16301789    }
     
    19922151    /** @since 0.7.14 */
    19932152    private static String toImg(String icon) {
    1994         return "<img alt=\"\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\">";
     2153        return "<img alt=\"\" height=\"16\" width=\"16\" src=\"/i2psnark/.icons/" + icon + ".png\">";
    19952154    }
    19962155
    19972156    /** @since 0.8.2 */
    19982157    private static String toImg(String icon, String altText) {
    1999         return "<img alt=\"" + altText + "\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\">";
     2158        return "<img alt=\"" + altText + "\" height=\"16\" width=\"16\" src=\"/i2psnark/.icons/" + icon + ".png\">";
    20002159    }
    20012160
  • apps/i2ptunnel/java/build.xml

    rf22ac28 rb0a682f  
    6464                <attribute name="Class-Path" value="i2p.jar mstreaming.jar" />
    6565                <attribute name="Implementation-Version" value="${full.version}" />
     66                <attribute name="Built-By" value="${build.built-by}" />
    6667                <attribute name="Build-Date" value="${build.timestamp}" />
    6768                <attribute name="Base-Revision" value="${workspace.version}" />
     
    137138            <manifest>
    138139                <attribute name="Implementation-Version" value="${full.version}" />
     140                <attribute name="Built-By" value="${build.built-by}" />
    139141                <attribute name="Build-Date" value="${build.timestamp}" />
    140142                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java

    rf22ac28 rb0a682f  
    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/wizard.jsp

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    118118        <jar destfile="./jettylib/org.mortbay.jetty.jar" basedir="./build/obj" includes="**/*.class" update="true" >
    119119            <manifest>
     120                <attribute name="Built-By" value="${build.built-by}" />
    120121                <attribute name="Build-Date" value="${build.timestamp}" />
    121122                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/ministreaming/java/build.xml

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    9393                <attribute name="Class-Path" value="i2p.jar router.jar jrobin.jar desktopgui.jar" />
    9494                <attribute name="Implementation-Version" value="${full.version}" />
     95                <attribute name="Built-By" value="${build.built-by}" />
    9596                <attribute name="Build-Date" value="${build.timestamp}" />
    9697                <attribute name="Base-Revision" value="${workspace.version}" />
     
    173174            <manifest>
    174175                <attribute name="Implementation-Version" value="${full.version}" />
     176                <attribute name="Built-By" value="${build.built-by}" />
    175177                <attribute name="Build-Date" value="${build.timestamp}" />
    176178                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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/ConfigNetHelper.java

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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/NetDbRenderer.java

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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/SummaryListener.java

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

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

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

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

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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

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

    rf22ac28 rb0a682f  
    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

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

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

    rf22ac28 rb0a682f  
    3737<html>
    3838<head>
    39 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     39<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    4040<title>${book.book} <%=intl._("addressbook")%> - susidns</title>
    4141<link rel="stylesheet" type="text/css" href="css.css">
     
    9595<td><a href="http://<%=b32%>/"><%=b32%></a></td>
    9696</tr><tr class="list${book.trClass}">
     97<td><%=intl._("Base 64 Hash")%></td>
     98<td><%=addr.getB64()%></td>
     99</tr><tr class="list${book.trClass}">
    97100<td><%=intl._("Address Helper")%></td>
    98101<td><a href="http://<%=addr.getName()%>/?i2paddresshelper=<%=addr.getDestination()%>"><%=intl._("link")%></a></td>
     
    120123</tr><tr class="list${book.trClass}">
    121124<td><%=intl._("Destination")%></td>
    122 <td class="destinations"><textarea rows="1" style="height: 3em;" cols="70" wrap="off" readonly="readonly" ><%=addr.getDestination()%></textarea></td>
     125<td class="destinations"><textarea rows="1" style="height:3em;" wrap="off" cols="70" readonly="readonly" ><%=addr.getDestination()%></textarea></td>
    123126</tr></table>
    124127</div>
  • apps/susidns/src/jsp/subscriptions.jsp

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

    rf22ac28 rb0a682f  
    4747            <manifest>
    4848                <attribute name="Implementation-Version" value="${full.version}" />
     49                <attribute name="Built-By" value="${build.built-by}" />
    4950                <attribute name="Build-Date" value="${build.timestamp}" />
    5051                <attribute name="Base-Revision" value="${workspace.version}" />
  • apps/systray/java/build.xml

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    167167                        excludes="org/jrobin/cmd/ org/jrobin/convertor/ org/jrobin/inspector/" />
    168168            <manifest>
     169                <attribute name="Built-By" value="${build.built-by}" />
    169170                <attribute name="Build-Date" value="${build.timestamp}" />
    170171                <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}" />
     
    545556
    546557    <target name="verifyReleaseBuildNumbers" depends="getReleaseNumber, getBuildNumber" >
     558        <echo message="SDK: ${java.vendor} ${java.version} (${java.runtime.name} ${java.runtime.version})" />
    547559        <fail message="Bad release number: ${release.number}" >
    548560            <condition>
     
    573585        <delete file="installer/lib/izpack/patches.jar" failonerror="false" quiet="true" />     
    574586        <delete file="i2pinstall.exe" failonerror="false" quiet="true" />       
    575         <delete file="i2p.exe" failonerror="false" quiet="true" />
    576587        <delete file="syndie-standalone.zip" failonerror="false" quiet="true" />
    577588        <delete>
     
    755766   
    756767    <target name="preppkg-windows" depends="preppkg-base, buildexe">
    757         <copy file="i2p.exe" todir="pkg-temp/" failonerror="false" />
     768        <copy file="build/i2p.exe" todir="pkg-temp/" failonerror="false" />
    758769        <copy file="apps/systray/java/lib/systray4j.dll" todir="pkg-temp/lib" />
    759770        <copy file="apps/systray/java/resources/iggy.ico" todir="pkg-temp/icons" />
     
    10171028        <!-- include systray changes in 0.7.5 -->
    10181029        <copy file="build/systray.jar" todir="pkg-temp/lib/" />
     1030       <!-- removed from updater in 0.9
    10191031        <copy file="build/desktopgui.jar" todir="pkg-temp/lib/" />
     1032       -->
    10201033        <copy file="build/susimail.war" todir="pkg-temp/webapps/" />
    10211034        <copy file="build/susidns.war" todir="pkg-temp/webapps/" />
     
    11171130            <manifest>
    11181131                <attribute name="Main-Class" value="net.i2p.util.Copy" />
     1132                <attribute name="Built-By" value="${build.built-by}" />
    11191133                <attribute name="Build-Date" value="${build.timestamp}" />
    11201134                <attribute name="Base-Revision" value="${workspace.version}" />
     
    11251139            <manifest>
    11261140                <attribute name="Main-Class" value="net.i2p.util.Delete" />
     1141                <attribute name="Built-By" value="${build.built-by}" />
    11271142                <attribute name="Build-Date" value="${build.timestamp}" />
    11281143                <attribute name="Base-Revision" value="${workspace.version}" />
     
    11331148            <manifest>
    11341149                <attribute name="Main-Class" value="net.i2p.util.Exec" />
     1150                <attribute name="Built-By" value="${build.built-by}" />
    11351151                <attribute name="Build-Date" value="${build.timestamp}" />
    11361152                <attribute name="Base-Revision" value="${workspace.version}" />
     
    11701186    </target>
    11711187
     1188    <!-- this makes i2pinstall.exe from install.jar -->
    11721189    <target name="doInstallerEXE" unless="noExe">
    11731190        <!-- now the installer exe -->
    11741191        <launch4j configFile="./installer/i2pinstaller.xml" />
    1175         <launch4j configFile="./installer/i2pstandalone.xml" />
    11761192        <!-- thazzit -->
    11771193    </target>
    11781194
    11791195    <!-- Custom installers -->
    1180     <target name="installer-nowindows" depends="clean, preppkg-nowindows, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
    1181         <mkdir dir="pkg-temp/installer" />
    1182         <!-- set if unset -->
    1183         <property name="workspace.changes.util.tr" value="" />
    1184         <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}.jar" installerType="standard" basedir="${basedir}" />
    1185     </target>
    1186 
    1187 
    1188     <target name="installer-freebsd" depends="clean, preppkg-freebsd-only, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
    1189         <mkdir dir="pkg-temp/installer" />
    1190         <!-- set if unset -->
    1191         <property name="workspace.changes.util.tr" value="" />
    1192         <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_freebsd-only.jar" installerType="standard" basedir="${basedir}" />
    1193     </target>
    1194 
    1195     <target name="installer-linux" depends="clean, preppkg-linux-only, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
    1196         <mkdir dir="pkg-temp/installer" />
    1197         <!-- set if unset -->
    1198         <property name="workspace.changes.util.tr" value="" />
    1199         <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_linux-only.jar" installerType="standard" basedir="${basedir}" />
    1200     </target>
    1201 
    1202 
    1203     <target name="installer-osx" depends="clean, checkForIzpack2App, preppkg-osx-only, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches">
    1204         <mkdir dir="pkg-temp/installer" />
     1196    <target name="installer-nowindows" depends="clean, preppkg-nowindows, izpack-patches" >
     1197        <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}.jar" installerType="standard" basedir="${basedir}" />
     1198    </target>
     1199
     1200
     1201    <target name="installer-freebsd" depends="clean, preppkg-freebsd-only, izpack-patches" >
     1202        <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_freebsd-only.jar" installerType="standard" basedir="${basedir}" />
     1203    </target>
     1204
     1205    <target name="installer-linux" depends="clean, preppkg-linux-only, izpack-patches" >
     1206        <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_linux-only.jar" installerType="standard" basedir="${basedir}" />
     1207    </target>
     1208
     1209
     1210    <target name="installer-osx" depends="clean, checkForIzpack2App, preppkg-osx-only, izpack-patches">
    12051211        <mkdir dir="pkg-temp/osx" />
    1206         <!-- set if unset -->
    1207         <property name="workspace.changes.util.tr" value="" />
    1208         <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_osx-only.jar" installerType="standard" basedir="${basedir}" />
     1212        <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_osx-only.jar" installerType="standard" basedir="${basedir}" />
    12091213        <ant target="installer2app" />
    12101214        <delete dir="pkg-temp/osx" />
     
    12191223        <exec executable="python" failonerror="true">
    12201224            <arg value="${user.home}/IzPack/utils/wrappers/izpack2app/izpack2app.py" />
    1221             <arg value="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_osx-only.jar" />
    1222             <arg value="${basedir}/pkg-temp/osx/i2p-${release.number}-${i2p.build.number}${build.extra}_osx-install.app" />
     1225            <arg value="${basedir}/i2pinstall_${full.version}_osx-only.jar" />
     1226            <arg value="${basedir}/pkg-temp/osx/i2p-${full.version}_osx-install.app" />
    12231227        </exec>
    12241228        <exec executable="chmod" failonerror="true" osfamily="unix">
    12251229                <arg value="755" />
    1226                 <arg value="${basedir}/pkg-temp/osx/i2p-${release.number}-${i2p.build.number}${build.extra}_osx-install.app/Contents/MacOS/JavaApplicationStub" />
     1230                <arg value="${basedir}/pkg-temp/osx/i2p-${full.version}_osx-install.app/Contents/MacOS/JavaApplicationStub" />
    12271231        </exec>
    12281232        <exec executable="tar" osfamily="unix" failonerror="true">
     
    12301234                <arg value="--group=root" />
    12311235                <arg value="-cjvf" />
    1232                 <arg value="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_osx.tar.bz2" />
     1236                <arg value="${basedir}/i2pinstall_${full.version}_osx.tar.bz2" />
    12331237                <arg value="-C" />
    12341238                <arg value="${basedir}/pkg-temp/osx" />
    1235                 <arg value="i2p-${release.number}-${i2p.build.number}${build.extra}_osx-install.app" />
     1239                <arg value="i2p-${full.version}_osx-install.app" />
    12361240        </exec>
    12371241    </target>
    12381242
    1239     <!-- 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
    1240      and will fail if they don't exist. Thankfully these files are so very small there's not much harm in including them.
    1241     -->
    1242     <target name="installer-windows" depends="clean, doBuildEXE, preppkg-windows-only, preppkg-unix, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
     1243    <target name="installer-windows" depends="clean, preppkg-windows-only, util-list-changes, izpack-patches" >
    12431244        <mkdir dir="pkg-temp/installer" />
    12441245        <!-- set if unset -->
     
    12471248            <manifest>
    12481249                <attribute name="Main-Class" value="net.i2p.util.Copy" />
     1250                <attribute name="Built-By" value="${build.built-by}" />
    12491251                <attribute name="Build-Date" value="${build.timestamp}" />
    12501252                <attribute name="Base-Revision" value="${workspace.version}" />
     
    12551257            <manifest>
    12561258                <attribute name="Main-Class" value="net.i2p.util.Delete" />
     1259                <attribute name="Built-By" value="${build.built-by}" />
    12571260                <attribute name="Build-Date" value="${build.timestamp}" />
    12581261                <attribute name="Base-Revision" value="${workspace.version}" />
     
    12631266            <manifest>
    12641267                <attribute name="Main-Class" value="net.i2p.util.Exec" />
     1268                <attribute name="Built-By" value="${build.built-by}" />
    12651269                <attribute name="Build-Date" value="${build.timestamp}" />
    12661270                <attribute name="Base-Revision" value="${workspace.version}" />
     
    12681272            </manifest>
    12691273        </jar>
    1270         <izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_windows-only.jar" installerType="standard" basedir="${basedir}" />
    1271         <delete dir="pkg-temp/win" />
     1274        <izpack input="${basedir}/installer/install.xml" output="${basedir}/install.jar" installerType="standard" basedir="${basedir}" />
     1275        <ant target="installerexe" />
     1276        <delete file="${basedir}/install.jar" />
     1277        <move file="${basedir}/i2pinstall.exe" tofile="${basedir}/i2pinstall_${full.version}_windows-only.exe" />
    12721278    </target>
    12731279
     
    13841390        <copy file="i2pupdate.zip" tofile="i2pupdate_${release.number}.zip" />
    13851391        <copy file="i2pinstall.exe" tofile="i2pinstall_${release.number}.exe" />
    1386         <delete file="i2pupdate.sud" failonerror="false" />
    1387         <delete file="i2pupdate.su2" failonerror="false" />
     1392        <delete file="i2pupdate.sud" />
     1393        <delete file="i2pupdate.su2" />
     1394        <!-- make this a lot easier by putting release.privkey=/path/to/privkey in override.properties -->
    13881395        <input message="Enter private signing key file:" addproperty="release.privkey" />
    13891396        <fail message="You must enter a path." >
     
    14951502            <arg value="i2pupdate_${release.number}.zip" />
    14961503        </exec>
     1504        <exec executable="chmod" failonerror="true">
     1505            <arg value="444" />
     1506            <arg value="i2pinstall_${release.number}.exe" />
     1507            <arg value="i2psource_${release.number}.tar.bz2" />
     1508            <arg value="i2pupdate_${release.number}.zip" />
     1509            <arg value="i2pupdate.su2" />
     1510            <arg value="i2pupdate.sud" />
     1511            <arg value="i2pinstall_${release.number}.exe.sig" />
     1512            <arg value="i2psource_${release.number}.tar.bz2.sig" />
     1513            <arg value="i2pupdate_${release.number}.zip.sig" />
     1514        </exec>
    14971515        <echo message="File sizes:" />
    14981516        <exec executable="ls" failonerror="true">
  • core/java/build.xml

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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

    rf22ac28 rb0a682f  
    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            }
    8484        }
    8585    }
     
    127127     */
    128128    public static abstract class TimedEvent implements Runnable {
     129        private final Log _log;
    129130        private SimpleTimer2 _pool;
    130131        private int _fuzz;
     
    137138            _pool = pool;
    138139            _fuzz = DEFAULT_FUZZ;
    139         }
     140            _log = I2PAppContext.getGlobalContext().logManager().getLog(SimpleTimer2.class);
     141        }
     142
    140143        /** automatically schedules, don't use this one if you have other things to do first */
    141144        public TimedEvent(SimpleTimer2 pool, long timeoutMs) {
  • history.txt

    rf22ac28 rb0a682f  
     12012-03-02 zzz
     2  * BlockfileNamingService: Add negative cache
     3  * Build: Add built-by to jars; check for corrupt jars on debug page
     4  * configstats.jsp: Hide log settings unless already enabled
     5  * DataStructures:
     6    - Remove static logs
     7    - Sort addresses in RouterInfo at initialization only;
     8      change from Set to List to save space
     9    - Remove unused counters in Lease to save space
     10    - Increase max leases to 16
     11  * Graphs:
     12    - New single graph page with easy resizing
     13    - Support graphing of previous intervals
     14  * i2pinstall.exe: Add icon
     15  * i2psnark:
     16    - Add tracker configuration form
     17    - Remove custom tracker option from create form
     18    - Add private torrent option
     19    - More icons in buttons
     20    - Use js for refresh
     21  * I2PTunnelHTTPClient:
     22    - Refactoring to use Java URI parser to better handle
     23      escapes, IPv6 addresses, ports
     24    - Rewrite i2paddresshelper scanning/removal
     25    - Refactor out local server code
     26    - Nicer address helper error page
     27  * NetDB:
     28    - Reenable verify of RI stores, disabled in 0.7.9,
     29      checkin comments claim reenabled in 0.7.10 but didn't happen.
     30    - Synchronize StoreJob.sendNext() to avoid dups
     31  * netdb.jsp: Fix debug leaseset count again
     32  * susidns: Add b64 hash to details page
     33
    134* 2012-02-27 0.8.13 released
    235
  • installer/i2pinstaller.xml

    rf22ac28 rb0a682f  
    66  <chdir>.</chdir>
    77  <customProcName>false</customProcName>
    8   <!--<icon>SimpleApp.ico</icon>-->
     8  <icon>resources/console.ico</icon>
    99  <jre>
    1010    <minVersion>1.5.0</minVersion>
  • installer/i2pstandalone.xml

    rf22ac28 rb0a682f  
    22  <headerType>0</headerType>
    33  <jar>../build/launchi2p.jar</jar>
    4   <outfile>../i2p.exe</outfile>
     4  <outfile>../build/i2p.exe</outfile>
    55  <errTitle>I2P</errTitle>
    66  <chdir>.</chdir>
  • installer/resources/themes/snark/ubergine/snark.css

    rf22ac28 rb0a682f  
    471471     background: #212 url('/themes/snark/ubergine/images/graytile.png');         
    472472     color: #f60;
    473      margin: 2px 0;
     473     margin: 2px 4px;
    474474}
    475475
     
    526526}
    527527
     528input.default { width: 1px; height: 1px; visibility: hidden; }
     529
    528530input.accept {
    529531     background: #989 url('../../console/images/accept.png') no-repeat 2px center;
     532     padding: 2px 3px 2px 20px !important;
     533     min-height: 22px;
     534}
     535
     536input.add {
     537     background: #989 url('../../console/images/add.png') no-repeat 2px center;
     538     padding: 2px 3px 2px 20px !important;
     539     min-height: 22px;
     540}
     541
     542input.create {
     543     background: #989 url('images/create.png') no-repeat 2px center;
     544     padding: 2px 3px 2px 20px !important;
     545     min-height: 22px;
     546}
     547
     548input.cancel {
     549     background: #989 url('../../console/images/cancel.png') no-repeat 2px center;
     550     padding: 2px 3px 2px 20px !important;
     551     min-height: 22px;
     552}
     553
     554input.create {
     555     background: #989 url('images/create.png') no-repeat 2px center;
     556     padding: 2px 3px 2px 20px !important;
     557     min-height: 22px;
     558}
     559
     560input.delete {
     561     background: #989 url('../../console/images/delete.png') no-repeat 2px center;
     562     padding: 2px 3px 2px 20px !important;
     563     min-height: 22px;
     564}
     565
     566input.reload {
     567     background: #989 url('../../console/images/arrow_refresh.png') no-repeat 2px center;
    530568     padding: 2px 3px 2px 20px !important;
    531569     min-height: 22px;
  • installer/resources/themes/snark/vanilla/snark.css

    rf22ac28 rb0a682f  
    494494     background: #fff /*url('/themes/snark/ubergine/images/graytile.png')*/;     
    495495     color: #000;
    496      margin: 2px 0;
     496     margin: 2px 4px;
    497497}
    498498
     
    550550}
    551551
     552input.default { width: 1px; height: 1px; visibility: hidden; }
     553
    552554input.accept {
    553555     background: #f3efc7 url('../../console/images/accept.png') no-repeat 2px center;
     556     padding: 2px 3px 2px 20px !important;
     557     min-height: 22px;
     558}
     559
     560input.add {
     561     background: #f3efc7 url('../../console/images/add.png') no-repeat 2px center;
     562     padding: 2px 3px 2px 20px !important;
     563     min-height: 22px;
     564}
     565
     566input.cancel {
     567     background: #f3efc7 url('../../console/images/cancel.png') no-repeat 2px center;
     568     padding: 2px 3px 2px 20px !important;
     569     min-height: 22px;
     570}
     571
     572input.create {
     573     background: #f3efc7 url('images/create.png') no-repeat 2px center;
     574     padding: 2px 3px 2px 20px !important;
     575     min-height: 22px;
     576}
     577
     578input.delete {
     579     background: #f3efc7 url('../../console/images/delete.png') no-repeat 2px center;
     580     padding: 2px 3px 2px 20px !important;
     581     min-height: 22px;
     582}
     583
     584input.reload {
     585     background: #f3efc7 url('../../console/images/arrow_refresh.png') no-repeat 2px center;
    554586     padding: 2px 3px 2px 20px !important;
    555587     min-height: 22px;
  • router/java/build.xml

    rf22ac28 rb0a682f  
    7474            <manifest>
    7575                <attribute name="Implementation-Version" value="${full.version}" />
     76                <attribute name="Built-By" value="${build.built-by}" />
    7677                <attribute name="Build-Date" value="${build.timestamp}" />
    7778                <attribute name="Base-Revision" value="${workspace.version}" />
  • router/java/src/net/i2p/router/Blocklist.java

    rf22ac28 rb0a682f  
    480480        RouterInfo pinfo = _context.netDb().lookupRouterInfoLocally(peer);
    481481        if (pinfo == null) return rv;
    482         Set<RouterAddress> paddr = pinfo.getAddresses();
    483         if (paddr == null || paddr.isEmpty())
    484             return rv;
    485482        String oldphost = null;
    486         List<RouterAddress> pladdr = new ArrayList(paddr);
    487483        // for each peer address
    488         for (int j = 0; j < paddr.size(); j++) {
    489             RouterAddress pa = (RouterAddress) pladdr.get(j);
    490             if (pa == null) continue;
     484        for (RouterAddress pa : pinfo.getAddresses()) {
    491485            String phost = pa.getOption("host");
    492486            if (phost == null) continue;
     
    788782        singles.addAll(_singleIPBlocklist);
    789783        if (!singles.isEmpty()) {
    790             out.write("<table><tr><th align=center colspan=2><b>");
     784            out.write("<table><tr><th align=\"center\" colspan=\"2\"><b>");
    791785            out.write(_("IPs Banned Until Restart"));
    792786            out.write("</b></td></tr>");
     
    796790                 if (ip < 0)
    797791                     continue;
    798                  out.write("<tr><td align=center width=50%>");
     792                 out.write("<tr><td align=\"center\" width=\"50%\">");
    799793                 out.write(toStr(ip));
    800                  out.write("</td><td width=50%>&nbsp;</td></tr>\n");
     794                 out.write("</td><td width=\"50%\">&nbsp;</td></tr>\n");
    801795            }
    802796            // then 128 - 255
     
    805799                 if (ip >= 0)
    806800                     break;
    807                  out.write("<tr><td align=center width=50%>");
     801                 out.write("<tr><td align=\"center\" width=\"50%\">");
    808802                 out.write(toStr(ip));
    809                  out.write("</td><td width=50%>&nbsp;</td></tr>\n");
     803                 out.write("</td><td width=\"50%\">&nbsp;</td></tr>\n");
    810804            }
    811805            out.write("</table>");
    812806        }
    813807        if (_blocklistSize > 0) {
    814             out.write("<table><tr><th align=center colspan=2><b>");
     808            out.write("<table><tr><th align=\"center\" colspan=\"2\"><b>");
    815809            out.write(_("IPs Permanently Banned"));
    816             out.write("</b></th></tr><tr><td align=center width=50%><b>");
     810            out.write("</b></th></tr><tr><td align=\"center\" width=\"50%\"><b>");
    817811            out.write(_("From"));
    818             out.write("</b></td><td align=center width=50%><b>");
     812            out.write("</b></td><td align=\"center\" width=\"50%\"><b>");
    819813            out.write(_("To"));
    820814            out.write("</b></td></tr>");
     
    826820                 if (from < 0)
    827821                     continue;
    828                  out.write("<tr><td align=center width=50%>"); out.write(toStr(from)); out.write("</td><td align=center width=50%>");
     822                 out.write("<tr><td align=\"center\" width=\"50%\">"); out.write(toStr(from)); out.write("</td><td align=\"center\" width=\"50%\">");
    829823                 int to = getTo(_blocklist[i]);
    830824                 if (to != from) {
     
    839833                 if (from >= 0)
    840834                     break;
    841                  out.write("<tr><td align=center width=50%>"); out.write(toStr(from)); out.write("</td><td align=center width=50%>");
     835                 out.write("<tr><td align=\"center\" width=\"50%\">"); out.write(toStr(from)); out.write("</td><td align=\"center\" width=\"50%\">");
    842836                 int to = getTo(_blocklist[i]);
    843837                 if (to != from) {
  • router/java/src/net/i2p/router/RouterVersion.java

    rf22ac28 rb0a682f  
    1919    public final static String ID = "Monotone";
    2020    public final static String VERSION = CoreVersion.VERSION;
    21     public final static long BUILD = 0;
     21    public final static long BUILD = 1;
    2222
    2323    /** for example "-test" */
  • router/java/src/net/i2p/router/StatisticsManager.java

    rf22ac28 rb0a682f  
    8686            long publishedUptime = _context.router().getUptime();
    8787            // Don't publish these for first hour
    88             if (publishedUptime > 62*60*1000)
     88            if (publishedUptime > 62*60*1000 && CoreVersion.VERSION.equals("0.8.13"))
    8989                includeAverageThroughput(stats);
    9090            //includeRate("router.invalidMessageTime", stats, new long[] { 10*60*1000 });
  • router/java/src/net/i2p/router/client/ClientConnectionRunner.java

    rf22ac28 rb0a682f  
    240240   
    241241    /**
    242      *  Send a DisconnectMessage and log with level Log.CRIT.
     242     *  Send a DisconnectMessage and log with level Log.ERROR.
    243243     *  This is always bad.
    244244     *  See ClientMessageEventListener.handleCreateSession()
     
    246246     */
    247247    void disconnectClient(String reason) {
    248         disconnectClient(reason, Log.CRIT);
     248        disconnectClient(reason, Log.ERROR);
    249249    }
    250250
     
    255255    void disconnectClient(String reason, int logLevel) {
    256256        if (_log.shouldLog(logLevel))
    257             _log.log(logLevel, "Disconnecting the client ("
    258                      + _config
    259                      + ") : " + reason);
     257            _log.log(logLevel, "Disconnecting the client - "
     258                     + reason
     259                     + " config: "
     260                     + _config);
    260261        DisconnectMessage msg = new DisconnectMessage();
    261262        msg.setReason(reason);
  • router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java

    rf22ac28 rb0a682f  
    3737 */
    3838public class ClientManagerFacadeImpl extends ClientManagerFacade implements InternalClientManager {
    39     private final static Log _log = new Log(ClientManagerFacadeImpl.class);
     39    private final Log _log;
    4040    private ClientManager _manager;
    4141    private RouterContext _context;
     
    4949    public ClientManagerFacadeImpl(RouterContext context) {
    5050        _context = context;
    51         _log.debug("Client manager facade created");
     51        _log = _context.logManager().getLog(ClientManagerFacadeImpl.class);
     52        //_log.debug("Client manager facade created");
    5253    }
    5354   
  • router/java/src/net/i2p/router/client/RequestLeaseSetJob.java

    rf22ac28 rb0a682f  
    2828 */
    2929class RequestLeaseSetJob extends JobImpl {
    30     private Log _log;
    31     private ClientConnectionRunner _runner;
    32     private LeaseSet _ls;
    33     private long _expiration;
    34     private Job _onCreate;
    35     private Job _onFail;
    36     private LeaseRequestState _requestState;
     30    private final Log _log;
     31    private final ClientConnectionRunner _runner;
     32    private final LeaseSet _ls;
     33    private final long _expiration;
     34    private final Job _onCreate;
     35    private final Job _onFail;
     36    private final LeaseRequestState _requestState;
    3737   
    3838    public RequestLeaseSetJob(RouterContext ctx, ClientConnectionRunner runner, LeaseSet set, long expiration, Job onCreate, Job onFail, LeaseRequestState state) {
     
    9393     */
    9494    private class CheckLeaseRequestStatus extends JobImpl {
    95         private LeaseRequestState _req;
    96         private long _start;
     95        private final LeaseRequestState _req;
     96        private final long _start;
    9797       
    9898        public CheckLeaseRequestStatus(RouterContext enclosingContext, LeaseRequestState state) {
     
    115115            } else {
    116116                RequestLeaseSetJob.CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetTimeout", 1, 0);
    117                 if (_log.shouldLog(Log.CRIT)) {
     117                if (_log.shouldLog(Log.ERROR)) {
    118118                    long waited = System.currentTimeMillis() - _start;
    119                     _log.log(Log.CRIT, "Failed to receive a leaseSet in the time allotted (" + waited + "): " + _req + " for "
     119                    _log.error("Failed to receive a leaseSet in the time allotted (" + waited + "): " + _req + " for "
    120120                             + _runner.getConfig().getDestination().calculateHash().toBase64());
    121121                }
  • router/java/src/net/i2p/router/networkdb/kademlia/FloodfillStoreJob.java

    rf22ac28 rb0a682f  
    6969            boolean isRouterInfo = data.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO;
    7070            long published = data.getDate();
    71             if (isRouterInfo) {
    72                 // Temporarily disable
    73                 return;
    74             }
     71
    7572            // we should always have exactly one successful entry
    7673            Hash sentTo = null;
  • router/java/src/net/i2p/router/networkdb/kademlia/FloodfillVerifyStoreJob.java

    rf22ac28 rb0a682f  
    217217                    _log.warn("Verify failed (older) for " + _key);
    218218                if (_log.shouldLog(Log.INFO))
    219                     _log.info("Rcvd older lease: " + dsm.getEntry());
     219                    _log.info("Rcvd older data: " + dsm.getEntry());
    220220            } else if (_message instanceof DatabaseSearchReplyMessage) {
    221221                // assume 0 old, all new, 0 invalid, 0 dup
  • router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseStoreMessageJob.java

    rf22ac28 rb0a682f  
    99 */
    1010
     11import java.util.Collection;
    1112import java.util.Date;
    12 import java.util.Set;
    1313
    1414import net.i2p.data.DatabaseEntry;
    1515import net.i2p.data.Hash;
    1616import net.i2p.data.LeaseSet;
     17import net.i2p.data.RouterAddress;
    1718import net.i2p.data.RouterIdentity;
    1819import net.i2p.data.RouterInfo;
     
    146147                                _log.warn("Blocklisting new peer " + key + ' ' + ri);
    147148                    } else {
    148                         Set oldAddr = prevNetDb.getAddresses();
    149                         Set newAddr = ri.getAddresses();
    150                         if (newAddr != null && (!newAddr.equals(oldAddr)) &&
     149                        Collection<RouterAddress> oldAddr = prevNetDb.getAddresses();
     150                        Collection<RouterAddress> newAddr = ri.getAddresses();
     151                        if ((!newAddr.equals(oldAddr)) &&
    151152                            (!getContext().shitlist().isShitlistedForever(key)) &&
    152153                            getContext().blocklist().isBlocklisted(key) &&
  • router/java/src/net/i2p/router/networkdb/kademlia/LocalHash.java

    rf22ac28 rb0a682f  
    2828 */
    2929class LocalHash extends Hash {
    30     private final static Log _log = new Log(LocalHash.class);
     30    //private final static Log _log = new Log(LocalHash.class);
    3131    private /* FIXME final FIXME */ Map<Hash, byte[]> _xorCache;
    3232
     
    8787                cached = _xorCache.size();
    8888            }
     89          /****
    8990            if (_log.shouldLog(Log.DEBUG)) {
    9091                // explicit buffer, since the compiler can't guess how long it'll be
     
    9596                _log.debug(buf.toString(), new Exception());
    9697            }
     98          ****/
    9799        } else {
     100          /****
    98101            if (_log.shouldLog(Log.DEBUG)) {
    99102                // explicit buffer, since the compiler can't guess how long it'll be
     
    104107                _log.debug(buf.toString());
    105108            }
     109          ****/
    106110        }
    107111        return distance;
  • router/java/src/net/i2p/router/networkdb/kademlia/MessageWrapper.java

    rf22ac28 rb0a682f  
    2828class MessageWrapper {
    2929
    30     private static final Log _log = RouterContext.getGlobalContext().logManager().getLog(MessageWrapper.class);
     30    //private static final Log _log = RouterContext.getGlobalContext().logManager().getLog(MessageWrapper.class);
    3131
    3232    private static final int NETDB_TAGS_TO_DELIVER = 6;
     
    7272        if (!sentTags.isEmpty())
    7373            tsh = skm.tagsDelivered(sentTo, sentKey, sentTags);
    74         if (_log.shouldLog(Log.DEBUG))
    75             _log.debug("Sent to: " + to.getIdentity().getHash() + " with key: " + sentKey + " and tags: " + sentTags.size());
     74        //if (_log.shouldLog(Log.DEBUG))
     75        //    _log.debug("Sent to: " + to.getIdentity().getHash() + " with key: " + sentKey + " and tags: " + sentTags.size());
    7676        return new WrappedMessage(msg, skm, sentTo, sentKey, tsh);
    7777    }
     
    104104            if (this.tsh != null) {
    105105                this.skm.tagsAcked(this.sentTo, this.sessionKey, this.tsh);
    106                 if (_log.shouldLog(Log.DEBUG))
    107                     _log.debug("Tags acked for key: " + this.sessionKey);
     106                //if (_log.shouldLog(Log.DEBUG))