Author: toad
Date: 2005-10-22 18:51:03 +0000 (Sat, 22 Oct 2005)
New Revision: 7447

Added:
   trunk/freenet/src/freenet/client/
   trunk/freenet/src/freenet/client/ArchiveHandler.java
   trunk/freenet/src/freenet/client/ArchiveManager.java
   trunk/freenet/src/freenet/client/ClientMetadata.java
   trunk/freenet/src/freenet/client/DefaultMIMETypes.java
   trunk/freenet/src/freenet/client/FetchException.java
   trunk/freenet/src/freenet/client/FetchResult.java
   trunk/freenet/src/freenet/client/Fetcher.java
   trunk/freenet/src/freenet/client/FetcherContext.java
   trunk/freenet/src/freenet/client/HighLevelSimpleClient.java
   trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
   trunk/freenet/src/freenet/client/InsertBlock.java
   trunk/freenet/src/freenet/client/Metadata.java
   trunk/freenet/src/freenet/client/MetadataParseException.java
   trunk/freenet/src/freenet/keys/ClientBlock.java
   trunk/freenet/src/freenet/keys/ClientKey.java
   trunk/freenet/src/freenet/keys/KeyBlock.java
   trunk/freenet/src/freenet/support/Bucket.java
   trunk/freenet/src/freenet/support/BucketFactory.java
   trunk/freenet/src/freenet/support/LRUHashtable.java
Modified:
   trunk/freenet/devnotes/specs/metadata-v0.txt
   trunk/freenet/src/freenet/keys/CHKBlock.java
   trunk/freenet/src/freenet/keys/ClientCHK.java
   trunk/freenet/src/freenet/keys/Key.java
   trunk/freenet/src/freenet/node/SimpleLowLevelClient.java
Log:
Beginnings of metadata (splitfiles, redirects, etc) support.
Yes, this breaks trunk.

Modified: trunk/freenet/devnotes/specs/metadata-v0.txt
===================================================================
--- trunk/freenet/devnotes/specs/metadata-v0.txt        2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/devnotes/specs/metadata-v0.txt        2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -15,7 +15,7 @@
 8 bytes - magic number for freenet metadata
 Wasted bytes, just being paranoid.

-1 byte - version number
+2 bytes - version number
 0 for now.

 1 byte - document type
@@ -49,14 +49,16 @@
 tar, with the compressed splitfile bit set, and then a codec specified
 below, for tar.gz, tar.bz2 etc)

-If a compressed splitfile:
+If a splitfile:
+8 bytes - real content length (uncompressed)
+-1 if we don't know (not allowed on splitfiles unless bit 6 set above)
+Note no 2GB limit. :)
+
+If compressed:
 2 bytes - codec ID
 Initially we only support gzip (0).
+8 bytes - decompressed content length

-8 bytes - real content length.
--1 if we don't know, and this is not a splitfile redirect.
-Note no 2GB limit. :)
-
 If has a MIME type:
 If raw:
 1 byte - length (N)
@@ -83,19 +85,22 @@


 For a simple redirect:
+
+If bit 5 is set above:
 1 byte - length of binary key
-N bytes - if bit 5 above is unset, which is the usual case, a compact
-binary representation of a simple CHK. Otherwise a full binary key,
-which can include anything a FreenetURI can include, and therefore is
-somewhat larger.
+N bytes - binary key (this is just a compressed FreenetURI)
+Else:
+<fixed number yet to be determined> bytes - raw binary form of a CHK

 For a splitfile redirect:
 2 bytes - algorithm ID
-0 = no redundancy. Invalid unless bit 6 above is set.
+0 = no redundancy. Invalid unless bit 6 or 5 above is set.
 1 = standard onion FEC algorithm
 ...
-2 bytes - number of blocks
-2 bytes - number of check blocks
+4 bytes - number of bytes of parameters
+N bytes - parameters (e.g. number of segments etc)
+4 bytes - number of blocks ( 2 bytes would have the 2GB limit )
+4 bytes - number of check blocks

 Followed by all the keys involved in the above format.

@@ -112,10 +117,10 @@
 4 bytes - number of redirects
 1 byte - length of redirect name
 N bytes - redirect name
-1 byte - document type
- All types above are valid, plus type 4 = redirect to file in ZIP
- manifest (if this manifest is in fact inside a ZIP manifest). If one of
- the above types is specified, then we include data exactly as above. If
- type 4 is specified:
+4 bytes - length of sub-document
+
+Then follows a document formatted as described above.
+If the manifest is inside a ZIP manifest, then type 4 = redirect to
+file in a ZIP manifest is valid:
 1 byte - length of name
 N bytes - name in ZIP file

Added: trunk/freenet/src/freenet/client/ArchiveHandler.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveHandler.java        2005-10-22 
18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/client/ArchiveHandler.java        2005-10-22 
18:51:03 UTC (rev 7447)
@@ -0,0 +1,12 @@
+package freenet.client;
+
+/**
+ * Handles a single archive for ZIP manifests.
+ */
+class ArchiveHandler {
+
+       public void finalize() {
+               // FIXME: implement
+       }
+       
+}

Added: trunk/freenet/src/freenet/client/ArchiveManager.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveManager.java        2005-10-22 
18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/client/ArchiveManager.java        2005-10-22 
18:51:03 UTC (rev 7447)
@@ -0,0 +1,46 @@
+package freenet.client;
+
+import java.io.File;
+import java.util.LinkedHashMap;
+import java.util.Set;
+
+import freenet.keys.ClientKey;
+import freenet.support.LRUHashtable;
+
+/**
+ * Cache of recently decoded archives:
+ * - Keep up to N ArchiveHandler's in RAM (this can be large; we don't keep the
+ * files open due to the limitations of the API)
+ * - Keep up to Y bytes (after padding and overheads) of decoded data on disk
+ * (the OS is quite capable of determining what to keep in actual RAM)
+ */
+public class ArchiveManager {
+
+       ArchiveManager(int maxHandlers) {
+               maxArchiveHandlers = maxHandlers;
+               archiveHandlers = new LRUHashtable();
+       }
+
+       // ArchiveHandler's
+       
+       final int maxArchiveHandlers;
+       final LRUHashtable archiveHandlers;
+       
+       public synchronized void putCached(ClientKey key, ArchiveHandler zip) {
+               archiveHandlers.push(key, zip);
+               while(archiveHandlers.size() > maxArchiveHandlers)
+                       ((ArchiveHandler) archiveHandlers.popKey()).finalize();
+       }
+
+       public ArchiveHandler getCached(ClientKey key) {
+               ArchiveHandler handler = (ArchiveHandler) 
archiveHandlers.get(key);
+               archiveHandlers.push(key, handler);
+               return handler;
+       }
+
+       // Data cache
+       
+       final long maxCachedData;
+       final File cacheDir;
+       final LRUHashtable storedData;
+}

Added: trunk/freenet/src/freenet/client/ClientMetadata.java
===================================================================
--- trunk/freenet/src/freenet/client/ClientMetadata.java        2005-10-22 
18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/client/ClientMetadata.java        2005-10-22 
18:51:03 UTC (rev 7447)
@@ -0,0 +1,17 @@
+package freenet.client;
+
+/**
+ * Stores the metadata that the client might actually be interested in.
+ */
+public class ClientMetadata {
+       
+       /** Default MIME type - what to set it to if we don't know any better */
+       public static final String DEFAULT_MIME_TYPE = 
"application/octet-stream";
+       
+       /** The document MIME type */
+       private String mimeType;
+
+       public String getMIMEType() {
+               return mimeType;
+       }
+}

Added: trunk/freenet/src/freenet/client/DefaultMIMETypes.java
===================================================================
--- trunk/freenet/src/freenet/client/DefaultMIMETypes.java      2005-10-22 
18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/client/DefaultMIMETypes.java      2005-10-22 
18:51:03 UTC (rev 7447)
@@ -0,0 +1,668 @@
+package freenet.client;
+
+import java.util.HashMap;
+import java.util.Vector;
+
+/**
+ * Holds the default MIME types.
+ */
+class DefaultMIMETypes {
+       
+       private static Vector mimeTypesByNumber = new Vector();
+       
+       private static HashMap mimeTypesByName = new HashMap();
+       
+       private static HashMap mimeTypesByExtension = new HashMap();
+       
+       protected static synchronized void addMIMEType(short number, String 
type) {
+               String s = (String) mimeTypesByNumber.get(number);
+               if(s != null) throw new IllegalArgumentException("Already used: 
"+number);
+               mimeTypesByNumber.set(number, type);
+               mimeTypesByName.put(type, new Short(number));
+       }
+       
+       protected static synchronized void addMIMEType(short number, String 
type, String[] extensions) {
+               addMIMEType(number, type);
+               Short t = new Short(type);
+               if(extensions != null)
+                       for(int i=0;i<extensions.length;i++)
+                               mimeTypesByExtension.put(extensions[i], t);
+       }
+       
+       protected static synchronized void addMIMEType(short number, String 
type, String extensions) {
+               addMIMEType(number, type, extensions.split(" "));
+       }
+       
+       public static String byNumber(short x) {
+               if(x > mimeTypesByNumber.size() || x < 0)
+                       return null;
+               return (String) mimeTypesByNumber.get(x);
+       }
+       
+       public static short byName(String s) {
+               Short x = (Short) mimeTypesByName.get(s);
+               if(x != null) return x.shortValue();
+               else return -1;
+       }
+       
+       // From toad's /etc/mime.types
+       // cat /etc/mime.types | sed "/^$/d;/#/d" | tr --squeeze '\t' ' ' | 
+       // (y=0; while read x; do echo "$x" | 
+       // sed -n "s/^\([^ ]*\)$/addMIMEType\($y, \"\1\"\);/p;s/^\([^ (),]\+\) 
\(.*\)$/addMIMEType\($y, \"\1\", \"\2\"\);/p;"; y=$((y+1)); done)
+       
+       static {
+               addMIMEType((short)0, "application/activemessage");
+               addMIMEType((short)1, "application/andrew-inset", "ez");
+               addMIMEType((short)2, "application/applefile");
+               addMIMEType((short)3, "application/atomicmail");
+               addMIMEType((short)4, "application/batch-SMTP");
+               addMIMEType((short)5, "application/beep+xml");
+               addMIMEType((short)6, "application/cals-1840");
+               addMIMEType((short)7, "application/commonground");
+               addMIMEType((short)8, "application/cu-seeme", "csm cu");
+               addMIMEType((short)9, "application/cybercash");
+               addMIMEType((short)10, "application/dca-rft");
+               addMIMEType((short)11, "application/dec-dx");
+               addMIMEType((short)12, "application/docbook+xml");
+               addMIMEType((short)13, "application/dsptype", "tsp");
+               addMIMEType((short)14, "application/dvcs");
+               addMIMEType((short)15, "application/edi-consent");
+               addMIMEType((short)16, "application/edifact");
+               addMIMEType((short)17, "application/edi-x12");
+               addMIMEType((short)18, "application/eshop");
+               addMIMEType((short)19, "application/font-tdpfr");
+               addMIMEType((short)20, "application/futuresplash", "spl");
+               addMIMEType((short)21, "application/ghostview");
+               addMIMEType((short)22, "application/hta", "hta");
+               addMIMEType((short)23, "application/http");
+               addMIMEType((short)24, "application/hyperstudio");
+               addMIMEType((short)25, "application/iges");
+               addMIMEType((short)26, "application/index");
+               addMIMEType((short)27, "application/index.cmd");
+               addMIMEType((short)28, "application/index.obj");
+               addMIMEType((short)29, "application/index.response");
+               addMIMEType((short)30, "application/index.vnd");
+               addMIMEType((short)31, "application/iotp");
+               addMIMEType((short)32, "application/ipp");
+               addMIMEType((short)33, "application/isup");
+               addMIMEType((short)34, "application/mac-compactpro", "cpt");
+               addMIMEType((short)35, "application/marc");
+               addMIMEType((short)36, "application/mac-binhex40", "hqx");
+               addMIMEType((short)37, "application/macwriteii");
+               addMIMEType((short)38, "application/mathematica", "nb");
+               addMIMEType((short)39, "application/mathematica-old");
+               addMIMEType((short)40, "application/msaccess", "mdb");
+               addMIMEType((short)41, "application/msword", "doc dot");
+               addMIMEType((short)42, "application/news-message-id");
+               addMIMEType((short)43, "application/news-transmission");
+               addMIMEType((short)44, "application/octet-stream", "bin");
+               addMIMEType((short)45, "application/ocsp-request");
+               addMIMEType((short)46, "application/ocsp-response");
+               addMIMEType((short)47, "application/oda", "oda");
+               addMIMEType((short)48, "application/ogg", "ogg");
+               addMIMEType((short)49, "application/parityfec");
+               addMIMEType((short)50, "application/pics-rules", "prf");
+               addMIMEType((short)51, "application/pgp-encrypted");
+               addMIMEType((short)52, "application/pgp-keys", "key");
+               addMIMEType((short)53, "application/pdf", "pdf");
+               addMIMEType((short)54, "application/pgp-signature", "pgp");
+               addMIMEType((short)55, "application/pkcs10");
+               addMIMEType((short)56, "application/pkcs7-mime");
+               addMIMEType((short)57, "application/pkcs7-signature");
+               addMIMEType((short)58, "application/pkix-cert");
+               addMIMEType((short)59, "application/pkixcmp");
+               addMIMEType((short)60, "application/pkix-crl");
+               addMIMEType((short)61, "application/postscript", "ps ai eps");
+               addMIMEType((short)62, 
"application/prs.alvestrand.titrax-sheet");
+               addMIMEType((short)63, "application/prs.cww");
+               addMIMEType((short)64, "application/prs.nprend");
+               addMIMEType((short)65, "application/qsig");
+               addMIMEType((short)66, "application/rar", "rar");
+               addMIMEType((short)67, "application/rdf+xml", "rdf");
+               addMIMEType((short)68, "application/remote-printing");
+               addMIMEType((short)69, "application/riscos");
+               addMIMEType((short)70, "application/rss+xml", "rss");
+               addMIMEType((short)71, "application/rtf", "rtf");
+               addMIMEType((short)72, "application/sdp");
+               addMIMEType((short)73, "application/set-payment");
+               addMIMEType((short)74, "application/set-payment-initiation");
+               addMIMEType((short)75, "application/set-registration");
+               addMIMEType((short)76, 
"application/set-registration-initiation");
+               addMIMEType((short)77, "application/sgml");
+               addMIMEType((short)78, "application/sgml-open-catalog");
+               addMIMEType((short)79, "application/sieve");
+               addMIMEType((short)80, "application/slate");
+               addMIMEType((short)81, "application/smil", "smi smil");
+               addMIMEType((short)82, "application/timestamp-query");
+               addMIMEType((short)83, "application/timestamp-reply");
+               addMIMEType((short)84, "application/vemmi");
+               addMIMEType((short)85, "application/whoispp-query");
+               addMIMEType((short)86, "application/whoispp-response");
+               addMIMEType((short)87, "application/wita");
+               addMIMEType((short)88, "application/wordperfect5.1", "wp5");
+               addMIMEType((short)89, "application/x400-bp");
+               addMIMEType((short)90, "application/xhtml+xml", "xht xhtml");
+               addMIMEType((short)91, "application/xml", "xml xsl");
+               addMIMEType((short)92, "application/xml-dtd");
+               addMIMEType((short)93, 
"application/xml-external-parsed-entity");
+               addMIMEType((short)94, "application/zip", "zip");
+               addMIMEType((short)95, "application/vnd.3M.Post-it-Notes");
+               addMIMEType((short)96, "application/vnd.accpac.simply.aso");
+               addMIMEType((short)97, "application/vnd.accpac.simply.imp");
+               addMIMEType((short)98, "application/vnd.acucobol");
+               addMIMEType((short)99, "application/vnd.aether.imp");
+               addMIMEType((short)100, 
"application/vnd.anser-web-certificate-issue-initiation");
+               addMIMEType((short)101, 
"application/vnd.anser-web-funds-transfer-initiation");
+               addMIMEType((short)102, "application/vnd.audiograph");
+               addMIMEType((short)103, "application/vnd.bmi");
+               addMIMEType((short)104, "application/vnd.businessobjects");
+               addMIMEType((short)105, "application/vnd.canon-cpdl");
+               addMIMEType((short)106, "application/vnd.canon-lips");
+               addMIMEType((short)107, "application/vnd.cinderella", "cdy");
+               addMIMEType((short)108, "application/vnd.claymore");
+               addMIMEType((short)109, "application/vnd.commerce-battelle");
+               addMIMEType((short)110, "application/vnd.commonspace");
+               addMIMEType((short)111, "application/vnd.comsocaller");
+               addMIMEType((short)112, "application/vnd.contact.cmsg");
+               addMIMEType((short)113, "application/vnd.cosmocaller");
+               addMIMEType((short)114, "application/vnd.ctc-posml");
+               addMIMEType((short)115, "application/vnd.cups-postscript");
+               addMIMEType((short)116, "application/vnd.cups-raster");
+               addMIMEType((short)117, "application/vnd.cups-raw");
+               addMIMEType((short)118, "application/vnd.cybank");
+               addMIMEType((short)119, "application/vnd.dna");
+               addMIMEType((short)120, "application/vnd.dpgraph");
+               addMIMEType((short)121, "application/vnd.dxr");
+               addMIMEType((short)122, "application/vnd.ecdis-update");
+               addMIMEType((short)123, "application/vnd.ecowin.chart");
+               addMIMEType((short)124, "application/vnd.ecowin.filerequest");
+               addMIMEType((short)125, "application/vnd.ecowin.fileupdate");
+               addMIMEType((short)126, "application/vnd.ecowin.series");
+               addMIMEType((short)127, "application/vnd.ecowin.seriesrequest");
+               addMIMEType((short)128, "application/vnd.ecowin.seriesupdate");
+               addMIMEType((short)129, "application/vnd.enliven");
+               addMIMEType((short)130, "application/vnd.epson.esf");
+               addMIMEType((short)131, "application/vnd.epson.msf");
+               addMIMEType((short)132, "application/vnd.epson.quickanime");
+               addMIMEType((short)133, "application/vnd.epson.salt");
+               addMIMEType((short)134, "application/vnd.epson.ssf");
+               addMIMEType((short)135, "application/vnd.ericsson.quickcall");
+               addMIMEType((short)136, "application/vnd.eudora.data");
+               addMIMEType((short)137, "application/vnd.fdf");
+               addMIMEType((short)138, "application/vnd.ffsns");
+               addMIMEType((short)139, "application/vnd.flographit");
+               addMIMEType((short)140, "application/vnd.framemaker");
+               addMIMEType((short)141, "application/vnd.fsc.weblaunch");
+               addMIMEType((short)142, "application/vnd.fujitsu.oasys");
+               addMIMEType((short)143, "application/vnd.fujitsu.oasys2");
+               addMIMEType((short)144, "application/vnd.fujitsu.oasys3");
+               addMIMEType((short)145, "application/vnd.fujitsu.oasysgp");
+               addMIMEType((short)146, "application/vnd.fujitsu.oasysprs");
+               addMIMEType((short)147, "application/vnd.fujixerox.ddd");
+               addMIMEType((short)148, "application/vnd.fujixerox.docuworks");
+               addMIMEType((short)149, 
"application/vnd.fujixerox.docuworks.binder");
+               addMIMEType((short)150, "application/vnd.fut-misnet");
+               addMIMEType((short)151, "application/vnd.grafeq");
+               addMIMEType((short)152, "application/vnd.groove-account");
+               addMIMEType((short)153, 
"application/vnd.groove-identity-message");
+               addMIMEType((short)154, "application/vnd.groove-injector");
+               addMIMEType((short)155, "application/vnd.groove-tool-message");
+               addMIMEType((short)156, "application/vnd.groove-tool-template");
+               addMIMEType((short)157, "application/vnd.groove-vcard");
+               addMIMEType((short)158, "application/vnd.hhe.lesson-player");
+               addMIMEType((short)159, "application/vnd.hp-HPGL");
+               addMIMEType((short)160, "application/vnd.hp-PCL");
+               addMIMEType((short)161, "application/vnd.hp-PCLXL");
+               addMIMEType((short)162, "application/vnd.hp-hpid");
+               addMIMEType((short)163, "application/vnd.hp-hps");
+               addMIMEType((short)164, "application/vnd.httphone");
+               addMIMEType((short)165, "application/vnd.hzn-3d-crossword");
+               addMIMEType((short)166, "application/vnd.ibm.MiniPay");
+               addMIMEType((short)167, "application/vnd.ibm.afplinedata");
+               addMIMEType((short)168, "application/vnd.ibm.modcap");
+               addMIMEType((short)169, "application/vnd.informix-visionary");
+               addMIMEType((short)170, "application/vnd.intercon.formnet");
+               addMIMEType((short)171, "application/vnd.intertrust.digibox");
+               addMIMEType((short)172, "application/vnd.intertrust.nncp");
+               addMIMEType((short)173, "application/vnd.intu.qbo");
+               addMIMEType((short)174, "application/vnd.intu.qfx");
+               addMIMEType((short)175, 
"application/vnd.irepository.package+xml");
+               addMIMEType((short)176, "application/vnd.is-xpr");
+               addMIMEType((short)177, 
"application/vnd.japannet-directory-service");
+               addMIMEType((short)178, 
"application/vnd.japannet-jpnstore-wakeup");
+               addMIMEType((short)179, 
"application/vnd.japannet-payment-wakeup");
+               addMIMEType((short)180, 
"application/vnd.japannet-registration");
+               addMIMEType((short)181, 
"application/vnd.japannet-registration-wakeup");
+               addMIMEType((short)182, 
"application/vnd.japannet-setstore-wakeup");
+               addMIMEType((short)183, 
"application/vnd.japannet-verification");
+               addMIMEType((short)184, 
"application/vnd.japannet-verification-wakeup");
+               addMIMEType((short)185, "application/vnd.koan");
+               addMIMEType((short)186, "application/vnd.lotus-1-2-3");
+               addMIMEType((short)187, "application/vnd.lotus-approach");
+               addMIMEType((short)188, "application/vnd.lotus-freelance");
+               addMIMEType((short)189, "application/vnd.lotus-notes");
+               addMIMEType((short)190, "application/vnd.lotus-organizer");
+               addMIMEType((short)191, "application/vnd.lotus-screencam");
+               addMIMEType((short)192, "application/vnd.lotus-wordpro");
+               addMIMEType((short)193, "application/vnd.mcd");
+               addMIMEType((short)194, "application/vnd.mediastation.cdkey");
+               addMIMEType((short)195, "application/vnd.meridian-slingshot");
+               addMIMEType((short)196, "application/vnd.mif", "mif");
+               addMIMEType((short)197, "application/vnd.minisoft-hp3000-save");
+               addMIMEType((short)198, 
"application/vnd.mitsubishi.misty-guard.trustweb");
+               addMIMEType((short)199, "application/vnd.mobius.daf");
+               addMIMEType((short)200, "application/vnd.mobius.dis");
+               addMIMEType((short)201, "application/vnd.mobius.msl");
+               addMIMEType((short)202, "application/vnd.mobius.plc");
+               addMIMEType((short)203, "application/vnd.mobius.txf");
+               addMIMEType((short)204, "application/vnd.motorola.flexsuite");
+               addMIMEType((short)205, 
"application/vnd.motorola.flexsuite.adsi");
+               addMIMEType((short)206, 
"application/vnd.motorola.flexsuite.fis");
+               addMIMEType((short)207, 
"application/vnd.motorola.flexsuite.gotap");
+               addMIMEType((short)208, 
"application/vnd.motorola.flexsuite.kmr");
+               addMIMEType((short)209, 
"application/vnd.motorola.flexsuite.ttc");
+               addMIMEType((short)210, 
"application/vnd.motorola.flexsuite.wem");
+               addMIMEType((short)211, "application/vnd.mozilla.xul+xml", 
"xul");
+               addMIMEType((short)212, "application/vnd.ms-artgalry");
+               addMIMEType((short)213, "application/vnd.ms-asf");
+               addMIMEType((short)214, "application/vnd.ms-excel", "xls xlb 
xlt");
+               addMIMEType((short)215, "application/vnd.ms-lrm");
+               addMIMEType((short)216, "application/vnd.ms-pki.seccat", "cat");
+               addMIMEType((short)217, "application/vnd.ms-pki.stl", "stl");
+               addMIMEType((short)218, "application/vnd.ms-powerpoint", "ppt 
pps");
+               addMIMEType((short)219, "application/vnd.ms-project");
+               addMIMEType((short)220, "application/vnd.ms-tnef");
+               addMIMEType((short)221, "application/vnd.ms-works");
+               addMIMEType((short)222, "application/vnd.mseq");
+               addMIMEType((short)223, "application/vnd.msign");
+               addMIMEType((short)224, "application/vnd.music-niff");
+               addMIMEType((short)225, "application/vnd.musician");
+               addMIMEType((short)226, "application/vnd.netfpx");
+               addMIMEType((short)227, "application/vnd.noblenet-directory");
+               addMIMEType((short)228, "application/vnd.noblenet-sealer");
+               addMIMEType((short)229, "application/vnd.noblenet-web");
+               addMIMEType((short)230, "application/vnd.novadigm.EDM");
+               addMIMEType((short)231, "application/vnd.novadigm.EDX");
+               addMIMEType((short)232, "application/vnd.novadigm.EXT");
+               addMIMEType((short)233, "application/vnd.osa.netdeploy");
+               addMIMEType((short)234, "application/vnd.palm");
+               addMIMEType((short)235, "application/vnd.pg.format");
+               addMIMEType((short)236, "application/vnd.pg.osasli");
+               addMIMEType((short)237, "application/vnd.powerbuilder6");
+               addMIMEType((short)238, "application/vnd.powerbuilder6-s");
+               addMIMEType((short)239, "application/vnd.powerbuilder7");
+               addMIMEType((short)240, "application/vnd.powerbuilder7-s");
+               addMIMEType((short)241, "application/vnd.powerbuilder75");
+               addMIMEType((short)242, "application/vnd.powerbuilder75-s");
+               addMIMEType((short)243, "application/vnd.previewsystems.box");
+               addMIMEType((short)244, 
"application/vnd.publishare-delta-tree");
+               addMIMEType((short)245, "application/vnd.pvi.ptid1");
+               addMIMEType((short)246, "application/vnd.pwg-xhtml-print+xml");
+               addMIMEType((short)247, "application/vnd.rapid");
+               addMIMEType((short)248, "application/vnd.s3sms");
+               addMIMEType((short)249, "application/vnd.seemail");
+               addMIMEType((short)250, 
"application/vnd.shana.informed.formdata");
+               addMIMEType((short)251, 
"application/vnd.shana.informed.formtemplate");
+               addMIMEType((short)252, 
"application/vnd.shana.informed.interchange");
+               addMIMEType((short)253, 
"application/vnd.shana.informed.package");
+               addMIMEType((short)254, "application/vnd.smaf", "mmf");
+               addMIMEType((short)255, "application/vnd.sss-cod");
+               addMIMEType((short)256, "application/vnd.sss-dtf");
+               addMIMEType((short)257, "application/vnd.sss-ntf");
+               addMIMEType((short)258, "application/vnd.stardivision.calc", 
"sdc");
+               addMIMEType((short)259, "application/vnd.stardivision.draw", 
"sda");
+               addMIMEType((short)260, "application/vnd.stardivision.impress", 
"sdd sdp");
+               addMIMEType((short)261, "application/vnd.stardivision.math", 
"smf");
+               addMIMEType((short)262, "application/vnd.stardivision.writer", 
"sdw vor");
+               addMIMEType((short)263, 
"application/vnd.stardivision.writer-global", "sgl");
+               addMIMEType((short)264, "application/vnd.street-stream");
+               addMIMEType((short)265, "application/vnd.sun.xml.calc", "sxc");
+               addMIMEType((short)266, 
"application/vnd.sun.xml.calc.template", "stc");
+               addMIMEType((short)267, "application/vnd.sun.xml.draw", "sxd");
+               addMIMEType((short)268, 
"application/vnd.sun.xml.draw.template", "std");
+               addMIMEType((short)269, "application/vnd.sun.xml.impress", 
"sxi");
+               addMIMEType((short)270, 
"application/vnd.sun.xml.impress.template", "sti");
+               addMIMEType((short)271, "application/vnd.sun.xml.math", "sxm");
+               addMIMEType((short)272, "application/vnd.sun.xml.writer", 
"sxw");
+               addMIMEType((short)273, 
"application/vnd.sun.xml.writer.global", "sxg");
+               addMIMEType((short)274, 
"application/vnd.sun.xml.writer.template", "stw");
+               addMIMEType((short)275, "application/vnd.svd");
+               addMIMEType((short)276, "application/vnd.swiftview-ics");
+               addMIMEType((short)277, "application/vnd.symbian.install", 
"sis");
+               addMIMEType((short)278, "application/vnd.triscape.mxs");
+               addMIMEType((short)279, "application/vnd.trueapp");
+               addMIMEType((short)280, "application/vnd.truedoc");
+               addMIMEType((short)281, "application/vnd.tve-trigger");
+               addMIMEType((short)282, "application/vnd.ufdl");
+               addMIMEType((short)283, "application/vnd.uplanet.alert");
+               addMIMEType((short)284, "application/vnd.uplanet.alert-wbxml");
+               addMIMEType((short)285, 
"application/vnd.uplanet.bearer-choice");
+               addMIMEType((short)286, 
"application/vnd.uplanet.bearer-choice-wbxml");
+               addMIMEType((short)287, "application/vnd.uplanet.cacheop");
+               addMIMEType((short)288, 
"application/vnd.uplanet.cacheop-wbxml");
+               addMIMEType((short)289, "application/vnd.uplanet.channel");
+               addMIMEType((short)290, 
"application/vnd.uplanet.channel-wbxml");
+               addMIMEType((short)291, "application/vnd.uplanet.list");
+               addMIMEType((short)292, "application/vnd.uplanet.list-wbxml");
+               addMIMEType((short)293, "application/vnd.uplanet.listcmd");
+               addMIMEType((short)294, 
"application/vnd.uplanet.listcmd-wbxml");
+               addMIMEType((short)295, "application/vnd.uplanet.signal");
+               addMIMEType((short)296, "application/vnd.vcx");
+               addMIMEType((short)297, "application/vnd.vectorworks");
+               addMIMEType((short)298, 
"application/vnd.vidsoft.vidconference");
+               addMIMEType((short)299, "application/vnd.visio", "vsd");
+               addMIMEType((short)300, "application/vnd.vividence.scriptfile");
+               addMIMEType((short)301, "application/vnd.wap.sic");
+               addMIMEType((short)302, "application/vnd.wap.slc");
+               addMIMEType((short)303, "application/vnd.wap.wbxml", "wbxml");
+               addMIMEType((short)304, "application/vnd.wap.wmlc", "wmlc");
+               addMIMEType((short)305, "application/vnd.wap.wmlscriptc", 
"wmlsc");
+               addMIMEType((short)306, "application/vnd.webturbo");
+               addMIMEType((short)307, "application/vnd.wrq-hp3000-labelled");
+               addMIMEType((short)308, "application/vnd.wt.stf");
+               addMIMEType((short)309, "application/vnd.xara");
+               addMIMEType((short)310, "application/vnd.xfdl");
+               addMIMEType((short)311, 
"application/vnd.yellowriver-custom-menu");
+               addMIMEType((short)312, "application/x-123", "wk");
+               addMIMEType((short)313, "application/x-apple-diskimage", "dmg");
+               addMIMEType((short)314, "application/x-bcpio", "bcpio");
+               addMIMEType((short)315, "application/x-bittorrent", "torrent");
+               addMIMEType((short)316, "application/x-cdf", "cdf");
+               addMIMEType((short)317, "application/x-cdlink", "vcd");
+               addMIMEType((short)318, "application/x-chess-pgn", "pgn");
+               addMIMEType((short)319, "application/x-chm", "chm");
+               addMIMEType((short)320, "application/x-core");
+               addMIMEType((short)321, "application/x-cpio", "cpio");
+               addMIMEType((short)322, "application/x-csh", "csh");
+               addMIMEType((short)323, "application/x-debian-package", "deb");
+               addMIMEType((short)324, "application/x-director", "dcr dir 
dxr");
+               addMIMEType((short)325, "application/x-doom", "wad");
+               addMIMEType((short)326, "application/x-dms", "dms");
+               addMIMEType((short)327, "application/x-dvi", "dvi");
+               addMIMEType((short)328, "application/x-executable");
+               addMIMEType((short)329, "application/x-flac", "flac");
+               addMIMEType((short)330, "application/x-font", "pfa pfb gsf pcf 
pcf.Z");
+               addMIMEType((short)331, "application/x-futuresplash", "spl");
+               addMIMEType((short)332, "application/x-gnumeric", "gnumeric");
+               addMIMEType((short)333, "application/x-go-sgf", "sgf");
+               addMIMEType((short)334, "application/x-graphing-calculator", 
"gcf");
+               addMIMEType((short)335, "application/x-gtar", "gtar tgz taz");
+               addMIMEType((short)336, "application/x-hdf", "hdf");
+               addMIMEType((short)337, "application/x-httpd-php", "phtml pht 
php");
+               addMIMEType((short)338, "application/x-httpd-php-source", 
"phps");
+               addMIMEType((short)339, "application/x-httpd-php3", "php3");
+               addMIMEType((short)340, 
"application/x-httpd-php3-preprocessed", "php3p");
+               addMIMEType((short)341, "application/x-httpd-php4", "php4");
+               addMIMEType((short)342, "application/x-ica", "ica");
+               addMIMEType((short)343, "application/x-internet-signup", "ins 
isp");
+               addMIMEType((short)344, "application/x-iphone", "iii");
+               addMIMEType((short)345, "application/x-java-applet");
+               addMIMEType((short)346, "application/x-java-archive", "jar");
+               addMIMEType((short)347, "application/x-java-bean");
+               addMIMEType((short)348, "application/x-java-jnlp-file", "jnlp");
+               addMIMEType((short)349, "application/x-java-serialized-object", 
"ser");
+               addMIMEType((short)350, "application/x-java-vm", "class");
+               addMIMEType((short)351, "application/x-javascript", "js");
+               addMIMEType((short)352, "application/x-kdelnk");
+               addMIMEType((short)353, "application/x-kchart", "chrt");
+               addMIMEType((short)354, "application/x-killustrator", "kil");
+               addMIMEType((short)355, "application/x-kpresenter", "kpr kpt");
+               addMIMEType((short)356, "application/x-koan", "skp skd skt 
skm");
+               addMIMEType((short)357, "application/x-kspread", "ksp");
+               addMIMEType((short)358, "application/x-kword", "kwd kwt");
+               addMIMEType((short)359, "application/x-latex", "latex");
+               addMIMEType((short)360, "application/x-lha", "lha");
+               addMIMEType((short)361, "application/x-lzh", "lzh");
+               addMIMEType((short)362, "application/x-lzx", "lzx");
+               addMIMEType((short)363, "application/x-maker", "frm maker frame 
fm fb book fbdoc");
+               addMIMEType((short)364, "application/x-mif", "mif");
+               addMIMEType((short)365, "application/x-ms-wmz", "wmz");
+               addMIMEType((short)366, "application/x-ms-wmd", "wmd");
+               addMIMEType((short)367, "application/x-msdos-program", "com exe 
bat dll");
+               addMIMEType((short)368, "application/x-msi", "msi");
+               addMIMEType((short)369, "application/x-netcdf", "nc");
+               addMIMEType((short)370, "application/x-ns-proxy-autoconfig", 
"pac");
+               addMIMEType((short)371, "application/x-nwc", "nwc");
+               addMIMEType((short)372, "application/x-object", "o");
+               addMIMEType((short)373, "application/x-oz-application", "oza");
+               addMIMEType((short)374, "application/x-pkcs7-certreqresp", 
"p7r");
+               addMIMEType((short)375, "application/x-pkcs7-crl", "crl");
+               addMIMEType((short)376, "application/x-python-code", "pyc pyo");
+               addMIMEType((short)377, "application/x-quicktimeplayer", "qtl");
+               addMIMEType((short)378, "application/x-redhat-package-manager", 
"rpm");
+               addMIMEType((short)379, "application/x-rx");
+               addMIMEType((short)380, "application/x-sh");
+               addMIMEType((short)381, "application/x-shar", "shar");
+               addMIMEType((short)382, "application/x-shellscript");
+               addMIMEType((short)383, "application/x-shockwave-flash", "swf 
swfl");
+               addMIMEType((short)384, "application/x-sh", "sh");
+               addMIMEType((short)385, "application/x-stuffit", "sit");
+               addMIMEType((short)386, "application/x-sv4cpio", "sv4cpio");
+               addMIMEType((short)387, "application/x-sv4crc", "sv4crc");
+               addMIMEType((short)388, "application/x-tar", "tar");
+               addMIMEType((short)389, "application/x-tcl", "tcl");
+               addMIMEType((short)390, "application/x-tex-gf", "gf");
+               addMIMEType((short)391, "application/x-tex-pk", "pk");
+               addMIMEType((short)392, "application/x-texinfo", "texinfo 
texi");
+               addMIMEType((short)393, "application/x-trash", "~ % bak old 
sik");
+               addMIMEType((short)394, "application/x-troff", "t tr roff");
+               addMIMEType((short)395, "application/x-troff-man", "man");
+               addMIMEType((short)396, "application/x-troff-me", "me");
+               addMIMEType((short)397, "application/x-troff-ms", "ms");
+               addMIMEType((short)398, "application/x-ustar", "ustar");
+               addMIMEType((short)399, "application/x-videolan");
+               addMIMEType((short)400, "application/x-wais-source", "src");
+               addMIMEType((short)401, "application/x-wingz", "wz");
+               addMIMEType((short)402, "application/x-x509-ca-cert", "crt");
+               addMIMEType((short)403, "application/x-xcf", "xcf");
+               addMIMEType((short)404, "application/x-xfig", "fig");
+               addMIMEType((short)405, "audio/32kadpcm");
+               addMIMEType((short)406, "audio/basic", "au snd");
+               addMIMEType((short)407, "audio/g.722.1");
+               addMIMEType((short)408, "audio/l16");
+               addMIMEType((short)409, "audio/midi", "mid midi kar");
+               addMIMEType((short)410, "audio/mp4a-latm");
+               addMIMEType((short)411, "audio/mpa-robust");
+               addMIMEType((short)412, "audio/mpeg", "mpga mpega mp2 mp3 m4a");
+               addMIMEType((short)413, "audio/mpegurl", "m3u");
+               addMIMEType((short)414, "audio/parityfec");
+               addMIMEType((short)415, "audio/prs.sid", "sid");
+               addMIMEType((short)416, "audio/telephone-event");
+               addMIMEType((short)417, "audio/tone");
+               addMIMEType((short)418, "audio/vnd.cisco.nse");
+               addMIMEType((short)419, "audio/vnd.cns.anp1");
+               addMIMEType((short)420, "audio/vnd.cns.inf1");
+               addMIMEType((short)421, "audio/vnd.digital-winds");
+               addMIMEType((short)422, "audio/vnd.everad.plj");
+               addMIMEType((short)423, "audio/vnd.lucent.voice");
+               addMIMEType((short)424, "audio/vnd.nortel.vbk");
+               addMIMEType((short)425, "audio/vnd.nuera.ecelp4800");
+               addMIMEType((short)426, "audio/vnd.nuera.ecelp7470");
+               addMIMEType((short)427, "audio/vnd.nuera.ecelp9600");
+               addMIMEType((short)428, "audio/vnd.octel.sbc");
+               addMIMEType((short)429, "audio/vnd.qcelp");
+               addMIMEType((short)430, "audio/vnd.rhetorex.32kadpcm");
+               addMIMEType((short)431, "audio/vnd.vmx.cvsd");
+               addMIMEType((short)432, "audio/x-aiff", "aif aiff aifc");
+               addMIMEType((short)433, "audio/x-gsm", "gsm");
+               addMIMEType((short)434, "audio/x-mpegurl", "m3u");
+               addMIMEType((short)435, "audio/x-ms-wma", "wma");
+               addMIMEType((short)436, "audio/x-ms-wax", "wax");
+               addMIMEType((short)437, "audio/x-pn-realaudio-plugin");
+               addMIMEType((short)438, "audio/x-pn-realaudio", "ra rm ram");
+               addMIMEType((short)439, "audio/x-realaudio", "ra");
+               addMIMEType((short)440, "audio/x-scpls", "pls");
+               addMIMEType((short)441, "audio/x-sd2", "sd2");
+               addMIMEType((short)442, "audio/x-wav", "wav");
+               addMIMEType((short)443, "chemical/x-pdb", "pdb");
+               addMIMEType((short)444, "chemical/x-xyz", "xyz");
+               addMIMEType((short)445, "image/cgm");
+               addMIMEType((short)446, "image/g3fax");
+               addMIMEType((short)447, "image/gif", "gif");
+               addMIMEType((short)448, "image/ief", "ief");
+               addMIMEType((short)449, "image/jpeg", "jpeg jpg jpe");
+               addMIMEType((short)450, "image/naplps");
+               addMIMEType((short)451, "image/pcx", "pcx");
+               addMIMEType((short)452, "image/png", "png");
+               addMIMEType((short)453, "image/prs.btif");
+               addMIMEType((short)454, "image/prs.pti");
+               addMIMEType((short)455, "image/svg+xml", "svg svgz");
+               addMIMEType((short)456, "image/tiff", "tiff tif");
+               addMIMEType((short)457, "image/vnd.cns.inf2");
+               addMIMEType((short)458, "image/vnd.djvu", "djvu djv");
+               addMIMEType((short)459, "image/vnd.dwg");
+               addMIMEType((short)460, "image/vnd.dxf");
+               addMIMEType((short)461, "image/vnd.fastbidsheet");
+               addMIMEType((short)462, "image/vnd.fpx");
+               addMIMEType((short)463, "image/vnd.fst");
+               addMIMEType((short)464, "image/vnd.fujixerox.edmics-mmr");
+               addMIMEType((short)465, "image/vnd.fujixerox.edmics-rlc");
+               addMIMEType((short)466, "image/vnd.mix");
+               addMIMEType((short)467, "image/vnd.net-fpx");
+               addMIMEType((short)468, "image/vnd.svf");
+               addMIMEType((short)469, "image/vnd.wap.wbmp", "wbmp");
+               addMIMEType((short)470, "image/vnd.xiff");
+               addMIMEType((short)471, "image/x-cmu-raster", "ras");
+               addMIMEType((short)472, "image/x-coreldraw", "cdr");
+               addMIMEType((short)473, "image/x-coreldrawpattern", "pat");
+               addMIMEType((short)474, "image/x-coreldrawtemplate", "cdt");
+               addMIMEType((short)475, "image/x-corelphotopaint", "cpt");
+               addMIMEType((short)476, "image/x-icon", "ico");
+               addMIMEType((short)477, "image/x-jg", "art");
+               addMIMEType((short)478, "image/x-jng", "jng");
+               addMIMEType((short)479, "image/x-ms-bmp", "bmp");
+               addMIMEType((short)480, "image/x-photoshop", "psd");
+               addMIMEType((short)481, "image/x-portable-anymap", "pnm");
+               addMIMEType((short)482, "image/x-portable-bitmap", "pbm");
+               addMIMEType((short)483, "image/x-portable-graymap", "pgm");
+               addMIMEType((short)484, "image/x-portable-pixmap", "ppm");
+               addMIMEType((short)485, "image/x-rgb", "rgb");
+               addMIMEType((short)486, "image/x-xbitmap", "xbm");
+               addMIMEType((short)487, "image/x-xpixmap", "xpm");
+               addMIMEType((short)488, "image/x-xwindowdump", "xwd");
+               addMIMEType((short)489, "inode/chardevice");
+               addMIMEType((short)490, "inode/blockdevice");
+               addMIMEType((short)491, "inode/directory-locked");
+               addMIMEType((short)492, "inode/directory");
+               addMIMEType((short)493, "inode/fifo");
+               addMIMEType((short)494, "inode/socket");
+               addMIMEType((short)495, "message/delivery-status");
+               addMIMEType((short)496, "message/disposition-notification");
+               addMIMEType((short)497, "message/external-body");
+               addMIMEType((short)498, "message/http");
+               addMIMEType((short)499, "message/s-http");
+               addMIMEType((short)500, "message/news");
+               addMIMEType((short)501, "message/partial");
+               addMIMEType((short)502, "message/rfc822");
+               addMIMEType((short)503, "model/iges", "igs iges");
+               addMIMEType((short)504, "model/mesh", "msh mesh silo");
+               addMIMEType((short)505, "model/vnd.dwf");
+               addMIMEType((short)506, "model/vnd.flatland.3dml");
+               addMIMEType((short)507, "model/vnd.gdl");
+               addMIMEType((short)508, "model/vnd.gs-gdl");
+               addMIMEType((short)509, "model/vnd.gtw");
+               addMIMEType((short)510, "model/vnd.mts");
+               addMIMEType((short)511, "model/vnd.vtu");
+               addMIMEType((short)512, "model/vrml", "wrl vrml");
+               addMIMEType((short)513, "multipart/alternative");
+               addMIMEType((short)514, "multipart/appledouble");
+               addMIMEType((short)515, "multipart/byteranges");
+               addMIMEType((short)516, "multipart/digest");
+               addMIMEType((short)517, "multipart/encrypted");
+               addMIMEType((short)518, "multipart/form-data");
+               addMIMEType((short)519, "multipart/header-set");
+               addMIMEType((short)520, "multipart/mixed");
+               addMIMEType((short)521, "multipart/parallel");
+               addMIMEType((short)522, "multipart/related");
+               addMIMEType((short)523, "multipart/report");
+               addMIMEType((short)524, "multipart/signed");
+               addMIMEType((short)525, "multipart/voice-message");
+               addMIMEType((short)526, "text/calendar", "ics icz");
+               addMIMEType((short)527, "text/comma-separated-values", "csv");
+               addMIMEType((short)528, "text/css", "css");
+               addMIMEType((short)529, "text/directory");
+               addMIMEType((short)530, "text/english");
+               addMIMEType((short)531, "text/enriched");
+               addMIMEType((short)532, "text/h323", "323");
+               addMIMEType((short)533, "text/html", "htm html shtml");
+               addMIMEType((short)534, "text/iuls", "uls");
+               addMIMEType((short)535, "text/mathml", "mml");
+               addMIMEType((short)536, "text/parityfec");
+               addMIMEType((short)537, "text/plain", "asc txt text diff pot");
+               addMIMEType((short)538, "text/prs.lines.tag");
+               addMIMEType((short)539, "text/rfc822-headers");
+               addMIMEType((short)540, "text/richtext", "rtx");
+               addMIMEType((short)541, "text/rtf", "rtf");
+               addMIMEType((short)542, "text/scriptlet", "sct wsc");
+               addMIMEType((short)543, "text/t140");
+               addMIMEType((short)544, "text/texmacs", "tm ts");
+               addMIMEType((short)545, "text/tab-separated-values", "tsv");
+               addMIMEType((short)546, "text/uri-list");
+               addMIMEType((short)547, "text/vnd.abc");
+               addMIMEType((short)548, "text/vnd.curl");
+               addMIMEType((short)549, "text/vnd.DMClientScript");
+               addMIMEType((short)550, "text/vnd.flatland.3dml");
+               addMIMEType((short)551, "text/vnd.fly");
+               addMIMEType((short)552, "text/vnd.fmi.flexstor");
+               addMIMEType((short)553, "text/vnd.in3d.3dml");
+               addMIMEType((short)554, "text/vnd.in3d.spot");
+               addMIMEType((short)555, "text/vnd.IPTC.NewsML");
+               addMIMEType((short)556, "text/vnd.IPTC.NITF");
+               addMIMEType((short)557, "text/vnd.latex-z");
+               addMIMEType((short)558, "text/vnd.motorola.reflex");
+               addMIMEType((short)559, "text/vnd.ms-mediapackage");
+               addMIMEType((short)560, "text/vnd.sun.j2me.app-descriptor", 
"jad");
+               addMIMEType((short)561, "text/vnd.wap.si");
+               addMIMEType((short)562, "text/vnd.wap.sl");
+               addMIMEType((short)563, "text/vnd.wap.wml", "wml");
+               addMIMEType((short)564, "text/vnd.wap.wmlscript", "wmls");
+               addMIMEType((short)565, "text/x-c++hdr", "h++ hpp hxx hh");
+               addMIMEType((short)566, "text/x-c++src", "c++ cpp cxx cc");
+               addMIMEType((short)567, "text/x-chdr", "h");
+               addMIMEType((short)568, "text/x-crontab");
+               addMIMEType((short)569, "text/x-csh", "csh");
+               addMIMEType((short)570, "text/x-csrc", "c");
+               addMIMEType((short)571, "text/x-java", "java");
+               addMIMEType((short)572, "text/x-makefile");
+               addMIMEType((short)573, "text/x-moc", "moc");
+               addMIMEType((short)574, "text/x-pascal", "p pas");
+               addMIMEType((short)575, "text/x-pcs-gcd", "gcd");
+               addMIMEType((short)576, "text/x-perl", "pl pm");
+               addMIMEType((short)577, "text/x-python", "py");
+               addMIMEType((short)578, "text/x-server-parsed-html");
+               addMIMEType((short)579, "text/x-setext", "etx");
+               addMIMEType((short)580, "text/x-sh", "sh");
+               addMIMEType((short)581, "text/x-tcl", "tcl tk");
+               addMIMEType((short)582, "text/x-tex", "tex ltx sty cls");
+               addMIMEType((short)583, "text/x-vcalendar", "vcs");
+               addMIMEType((short)584, "text/x-vcard", "vcf");
+               addMIMEType((short)585, "video/dl", "dl");
+               addMIMEType((short)586, "video/fli", "fli");
+               addMIMEType((short)587, "video/gl", "gl");
+               addMIMEType((short)588, "video/mpeg", "mpeg mpg mpe");
+               addMIMEType((short)589, "video/mp4", "mp4");
+               addMIMEType((short)590, "video/quicktime", "qt mov");
+               addMIMEType((short)591, "video/mp4v-es");
+               addMIMEType((short)592, "video/parityfec");
+               addMIMEType((short)593, "video/pointer");
+               addMIMEType((short)594, "video/vnd.fvt");
+               addMIMEType((short)595, "video/vnd.motorola.video");
+               addMIMEType((short)596, "video/vnd.motorola.videop");
+               addMIMEType((short)597, "video/vnd.mpegurl", "mxu");
+               addMIMEType((short)598, "video/vnd.mts");
+               addMIMEType((short)599, 
"video/vnd.nokia.interleaved-multimedia");
+               addMIMEType((short)600, "video/vnd.vivo");
+               addMIMEType((short)601, "video/x-dv", "dif dv");
+               addMIMEType((short)602, "video/x-la-asf", "lsf lsx");
+               addMIMEType((short)603, "video/x-mng", "mng");
+               addMIMEType((short)604, "video/x-ms-asf", "asf asx");
+               addMIMEType((short)605, "video/x-ms-wm", "wm");
+               addMIMEType((short)606, "video/x-ms-wmv", "wmv");
+               addMIMEType((short)607, "video/x-ms-wmx", "wmx");
+               addMIMEType((short)608, "video/x-ms-wvx", "wvx");
+               addMIMEType((short)609, "video/x-msvideo", "avi");
+               addMIMEType((short)610, "video/x-sgi-movie", "movie");
+               addMIMEType((short)611, "x-conference/x-cooltalk", "ice");
+               addMIMEType((short)612, "x-world/x-vrml", "vrm vrml wrl");
+       }
+}

Added: trunk/freenet/src/freenet/client/FetchException.java
===================================================================
--- trunk/freenet/src/freenet/client/FetchException.java        2005-10-22 
18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/client/FetchException.java        2005-10-22 
18:51:03 UTC (rev 7447)
@@ -0,0 +1,18 @@
+package freenet.client;
+
+public class FetchException extends Exception {
+
+       final int mode;
+       
+       public FetchException(int m) {
+               mode = m;
+       }
+
+       /** Too many levels of recursion into archives */
+       static final int TOO_DEEP_ARCHIVE_RECURSION = 1;
+       /** Don't know what to do with splitfile */
+       static final int UNKNOWN_SPLITFILE_METADATA = 2;
+       /** Don't know what to do with metadata */
+       static final int UNKNOWN_METADATA = 3;
+       
+}

Added: trunk/freenet/src/freenet/client/FetchResult.java
===================================================================
--- trunk/freenet/src/freenet/client/FetchResult.java   2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/client/FetchResult.java   2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -0,0 +1,50 @@
+package freenet.client;
+
+import freenet.support.Bucket;
+
+/**
+ * Class to contain the result of a key fetch.
+ */
+public class FetchResult {
+
+       final boolean succeeded;
+       final ClientMetadata metadata;
+       final Bucket data;
+       
+       public FetchResult(ClientMetadata dm, Bucket fetched) {
+               metadata = dm;
+               data = fetched;
+               succeeded = true;
+       }
+
+       /** Did it succeed? */
+       public boolean succeeded() {
+               return succeeded;
+       }
+       
+       /** If so, get the MIME type */
+       public String getMimeType() {
+               return metadata.getMIMEType();
+       }
+
+       public ClientMetadata getMetadata() {
+               return metadata;
+       }
+
+       /** @return The size of the data fetched, in bytes. */
+       public long size() {
+               return data.size();
+       }
+       
+       /** Get the result as a simple byte array, even if we don't have it
+        * as one. @throws OutOfMemoryError !!
+        */
+       public byte[] asByteArray() {
+               return data.toByteArray();
+       }
+       
+       /** Get the result as a Bucket */
+       public Bucket asBucket() {
+               return data;
+       }
+}

Added: trunk/freenet/src/freenet/client/Fetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/Fetcher.java       2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/client/Fetcher.java       2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -0,0 +1,135 @@
+package freenet.client;
+
+import freenet.keys.ClientKey;
+import freenet.keys.FreenetURI;
+import freenet.keys.KeyBlock;
+import freenet.node.SimpleLowLevelClient;
+import freenet.support.Bucket;
+import freenet.support.BucketFactory;
+
+/** Class that does the actual fetching. Does not have to have a user friendly
+ * interface!
+ */
+class Fetcher {
+
+       final FreenetURI origURI;
+       final FetcherContext ctx;
+       
+       public Fetcher(FreenetURI uri, FetcherContext ctx) {
+               this.origURI = uri;
+               this.ctx = ctx;
+       }
+
+       /**
+        * Run the actual fetch.
+        * @return The result of the fetch - successful or not.
+        */
+       public FetchResult run(int archiveRecursionLevel) {
+               if(archiveRecursionLevel > ctx.maxArchiveRecursionLevel) {
+                       throw new 
FetchException(FetchException.TOO_DEEP_ARCHIVE_RECURSION);
+               }
+               FreenetURI uri = origURI;
+               ClientKey key = ClientKey.get(origURI);
+               ClientMetadata dm = new ClientMetadata();
+               ArchiveHandler zip = null;
+               
+               for(int i=0;i<ctx.maxRedirects;i++) {
+                       // We have moved on to a new key, so we are not in the 
same ZIP
+                       zip = null;
+                       
+                       // Fetch the first key
+                       KeyBlock block = ctx.client.getKey(key);
+                       
+                       byte[] data = block.decode(key);
+                       
+                       if(!key.isMetadata()) {
+                               // Just return the data
+                               return new FetchResult(dm, 
ctx.bucketFactory.makeImmutableBucket(data));
+                       }
+                       
+                       // Else need to parse the metadata
+                       // This will throw if it finds an error, including 
semi-errors
+                       // such as too-big-indirect-metadata
+                       Metadata metadata = new Metadata(data);
+                       
+                       while(true) {
+                               
+                               if(metadata == null && key != null) {
+                                       // Try next key
+                                       break;
+                               }
+                               
+                               if(metadata.isSimpleManifest()) {
+                                       // Need a name from the URI
+                                       String name = uri.getMetaString();
+                                       
+                                       // Since metadata is a document, we 
just replace metadata here
+                                       if(name == null) {
+                                               metadata = 
metadata.getDefaultDocument();
+                                       } else {
+                                               metadata = 
metadata.getDocument(name);
+                                               uri = uri.popMetaString();
+                                       }
+                                       continue; // process the new metadata
+                               } else if(metadata.isSingleFileRedirect()) {
+                                       key = metadata.getSingleTarget();
+                                       if(metadata.isArchiveManifest()) {
+                                               zip = 
ctx.archiveManager.makeHandler(key, archiveRecursionLevel + 1, context);
+                                               Bucket metadataBucket = 
zip.getMetadata();
+                                               metadata = new 
Metadata(metadataBucket);
+                                               continue;
+                                       }
+                                       metadata = null;
+                                       
dm.mergeNoOverwrite(metadata.getDocumentMetadata());
+                                       continue;
+                               } else if(metadata.isZIPInternalRedirect() && 
zip != null) {
+                                       /** This is the whole document:
+                                        * Metadata: ZIP manifest -> fetch ZIP 
file, read .metadata
+                                        * .metadata: simple manifest -> look 
up filename ->
+                                        * filename's document -> is 
ZIP-internal-redirect
+                                        * Only valid if we are in a ZIP 
manifest.
+                                        * 
+                                        * Now, retreive the data
+                                        */
+                                       Bucket result = 
zip.get(metadata.getZIPInternalName());
+                                       
dm.mergeNoOverwrite(metadata.getDocumentMetadata());
+                                       return new FetchResult(dm, result);
+                               } else if(metadata.isSplitfile()) {
+                                       
+                                       int j;
+                                       for(j=0;j<ctx.maxLevels;j++) {
+                                       
+                                               // FIXME need to pass in 
whatever settings SF wants above
+                                               SplitFetcher sf = new 
SplitFetcher(metadata, ctx.maxTempLength);
+                                               Bucket sfResult = sf.run(); // 
will throw in event of error
+                                               
+                                               
if(metadata.isSimpleSplitfile()) {
+                                                       return new 
FetchResult(metadata.getDocumentMetadata(), sfResult);
+                                               } else 
if(metadata.isMultiLevelMetadata()) {
+                                                       metadata = new 
Metadata(sfResult);
+                                                       
if(!metadata.isMultiLevelMetadata())
+                                                               break; // try 
the new metadata
+                                               } else 
if(metadata.isArchiveManifest()) {
+                                                       zip = 
ctx.archiveManager.getHandler(key, archiveRecursionLevel + 1, context);
+                                                       Bucket metadataBucket = 
zip.getMetadata();
+                                                       metadata = new 
Metadata(metadataBucket);
+                                                       break;
+                                               } else {
+                                                       throw new 
FetchException(FetchException.UNKNOWN_SPLITFILE_METADATA);
+                                               }
+                                       } // loop (splitfile levels)
+                                       if(j>=ctx.maxLevels) {
+                                               // Too many levels
+                                               // FIXME: throw something
+                                       }
+                               } else {
+                                       throw new 
FetchException(FetchException.UNKNOWN_METADATA);
+                               }
+                       } // loop (metadata)
+               } // loop (redirects)
+               // Too many redirects
+               // FIXME Throw an exception
+               // TODO Auto-generated method stub
+               return null;
+       }
+}

Added: trunk/freenet/src/freenet/client/FetcherContext.java
===================================================================
--- trunk/freenet/src/freenet/client/FetcherContext.java        2005-10-22 
18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/client/FetcherContext.java        2005-10-22 
18:51:03 UTC (rev 7447)
@@ -0,0 +1,31 @@
+package freenet.client;
+
+import freenet.node.SimpleLowLevelClient;
+import freenet.support.BucketFactory;
+
+/** Context for a Fetcher */
+public class FetcherContext {
+       
+       final SimpleLowLevelClient client;
+       final long maxOutputLength;
+       final long maxTempLength;
+       final int maxRedirects;
+       final int maxLevels;
+       final int maxArchiveRecursionLevel;
+       final ArchiveManager archiveManager;
+       final BucketFactory bucketFactory;
+       
+       public FetcherContext(SimpleLowLevelClient client, long curMaxLength, 
+                       long curMaxTempLength, int maxRedirects, int maxLevels, 
int maxArchives, 
+                       ArchiveManager archiveManager, BucketFactory 
bucketFactory) {
+               this.client = client;
+               this.maxOutputLength = curMaxLength;
+               this.maxTempLength = curMaxTempLength;
+               this.maxRedirects = maxRedirects;
+               this.maxLevels = maxLevels;
+               this.maxArchiveRecursionLevel = maxArchives;
+               this.archiveManager = archiveManager;
+               this.bucketFactory = bucketFactory;
+       }
+
+}

Added: trunk/freenet/src/freenet/client/HighLevelSimpleClient.java
===================================================================
--- trunk/freenet/src/freenet/client/HighLevelSimpleClient.java 2005-10-22 
18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/client/HighLevelSimpleClient.java 2005-10-22 
18:51:03 UTC (rev 7447)
@@ -0,0 +1,26 @@
+package freenet.client;
+
+import freenet.keys.FreenetURI;
+
+public interface HighLevelSimpleClient {
+
+       /**
+        * Set the maximum length of the fetched data.
+        */
+       public void setMaxLength(long maxLength);
+       
+       /**
+        * Set the maximum length of any intermediate data, e.g. ZIP manifests.
+        */
+       public void setMaxIntermediateLength(long maxIntermediateLength);
+
+       /**
+        * Blocking fetch of a URI
+        */
+       public FetchResult fetch(FreenetURI uri);
+
+       /**
+        * Blocking insert of a URI
+        */
+       public FreenetURI insert(InsertBlock insert);
+}

Added: trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2005-10-22 18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2005-10-22 18:51:03 UTC (rev 7447)
@@ -0,0 +1,34 @@
+package freenet.client;
+
+import freenet.keys.FreenetURI;
+import freenet.node.SimpleLowLevelClient;
+
+public class HighLevelSimpleClientImpl implements HighLevelSimpleClient {
+
+       private SimpleLowLevelClient client;
+       private long curMaxLength;
+       private long curMaxTempLength;
+       
+       public HighLevelSimpleClientImpl(SimpleLowLevelClient client) {
+               this.client = client;
+       }
+       
+       public void setMaxLength(long maxLength) {
+               curMaxLength = maxLength;
+       }
+
+       public void setMaxIntermediateLength(long maxIntermediateLength) {
+               curMaxTempLength = maxIntermediateLength;
+       }
+
+       public FetchResult fetch(FreenetURI uri) {
+               Fetcher f = new Fetcher(uri, client, curMaxLength, 
curMaxTempLength);
+               return f.run(0);
+       }
+
+       public FreenetURI insert(InsertBlock insert) {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+}

Added: trunk/freenet/src/freenet/client/InsertBlock.java
===================================================================
--- trunk/freenet/src/freenet/client/InsertBlock.java   2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/client/InsertBlock.java   2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -0,0 +1,18 @@
+package freenet.client;
+
+import freenet.support.Bucket;
+
+/**
+ * Class to contain everything needed for an insert.
+ */
+public class InsertBlock {
+
+       private Bucket data;
+       private String mimeType;
+       
+       public InsertBlock(Bucket data, String mimeType) {
+               this.data = data;
+               this.mimeType = mimeType;
+       }
+
+}

Added: trunk/freenet/src/freenet/client/Metadata.java
===================================================================
--- trunk/freenet/src/freenet/client/Metadata.java      2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/client/Metadata.java      2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -0,0 +1,286 @@
+package freenet.client;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+
+import freenet.keys.FreenetURI;
+import freenet.support.Bucket;
+import freenet.support.Logger;
+
+/** Metadata parser/writer class. */
+public class Metadata {
+
+       static final long FREENET_METADATA_MAGIC = 0xf053b2842d91482bL;
+       static final int MAX_SPLITFILE_PARAMS_LENGTH = 32768;
+       /** Soft limit, to avoid memory DoS */
+       static final int MAX_SPLITFILE_BLOCKS = 100*1000;
+       
+       /** Parse some metadata from a byte[] 
+        * @throws IOException If the data is incomplete, or something wierd 
happens. */
+       public Metadata(byte[] data) throws IOException {
+               this(new DataInputStream(new ByteArrayInputStream(data)), 
false, data.length);
+       }
+
+       /** Parse some metadata from a Bucket 
+        * @throws IOException If the data is incomplete, or something wierd 
happens. */
+       public Metadata(Bucket meta) throws IOException {
+               this(new DataInputStream(meta.getInputStream()), false, 
meta.size());
+       }
+
+       /** Parse some metadata from a DataInputStream
+        * @throws IOException If an I/O error occurs, or the data is 
incomplete. */
+       public Metadata(DataInputStream dis, boolean 
acceptZipInternalRedirects, long length) throws IOException {
+               long magic = dis.readLong();
+               if(magic != FREENET_METADATA_MAGIC)
+                       throw new MetadataParseException("Invalid magic 
"+magic);
+               short version = dis.readShort();
+               if(version != 0)
+                       throw new MetadataParseException("Unsupported version 
"+version);
+               documentType = dis.readByte();
+               if(documentType < 0 || documentType > 5 || 
+                               (documentType == ZIP_INTERNAL_REDIRECT && 
!acceptZipInternalRedirects))
+                       throw new MetadataParseException("Unsupported document 
type: "+documentType);
+               if(documentType == SIMPLE_REDIRECT || documentType == 
MULTI_LEVEL_METADATA
+                               || documentType == ZIP_MANIFEST) {
+                       short flags = dis.readShort();
+                       splitfile = (flags & FLAGS_SPLITFILE) == 
FLAGS_SPLITFILE;
+                       dbr = (flags & FLAGS_DBR) == FLAGS_DBR;
+                       noMIME = (flags & FLAGS_NO_MIME) == FLAGS_NO_MIME;
+                       compressedMIME = (flags & FLAGS_COMPRESSED_MIME) == 
FLAGS_COMPRESSED_MIME;
+                       extraMetadata = (flags & FLAGS_EXTRA_METADATA) == 
FLAGS_EXTRA_METADATA;
+                       fullKeys = (flags & FLAGS_FULL_KEYS) == FLAGS_FULL_KEYS;
+                       splitUseLengths = (flags & FLAGS_SPLIT_USE_LENGTHS) == 
FLAGS_SPLIT_USE_LENGTHS;
+                       compressed = (flags & FLAGS_COMPRESSED) == 
FLAGS_COMPRESSED;
+               }
+               
+               if(documentType == ZIP_MANIFEST) {
+                       archiveType = dis.readShort();
+                       if(archiveType != ARCHIVE_ZIP)
+                               throw new MetadataParseException("Unrecognized 
archive type "+archiveType);
+               }
+
+               if(splitfile) {
+                       dataLength = dis.readLong();
+                       if(dataLength < -1)
+                               throw new MetadataParseException("Invalid real 
content length "+dataLength);
+                       
+                       if(dataLength == -1) {
+                               if(splitfile && !splitUseLengths)
+                                       throw new 
MetadataParseException("Splitfile must have a real-length");
+                       }
+               }
+               
+               if(compressed) {
+                       compressionCodec = dis.readShort();
+                       if(compressionCodec != COMPRESS_GZIP)
+                               throw new MetadataParseException("Unrecognized 
splitfile compression codec "+compressionCodec);
+                       
+                       decompressedLength = dis.readLong();
+               }
+               
+               if(noMIME) {
+                       mimeType = ClientMetadata.DEFAULT_MIME_TYPE;
+               } else {
+                       if(compressedMIME) {
+                               short x = dis.readShort();
+                               compressedMIMEValue = (short) (x & 32767); // 
chop off last bit
+                               hasCompressedMIMEParams = 
((int)compressedMIMEValue & 32768) == 32768;
+                               if(hasCompressedMIMEParams) {
+                                       compressedMIMEParams = dis.readShort();
+                                       if(compressedMIMEParams != 0) {
+                                               throw new 
MetadataParseException("Unrecognized MIME params ID (not yet implemented)");
+                                       }
+                               }
+                               mimeType = DefaultMIMETypes.byNumber(x);
+                       } else {
+                               // Read an actual raw MIME type
+                               byte l = dis.readByte();
+                               int len = l & 0xff; // positive
+                               byte[] toRead = new byte[len];
+                               dis.readFully(toRead);
+                               // MIME types are all ISO-8859-1, right?
+                               mimeType = new String(toRead);
+                       }
+               }
+               
+               if(dbr) {
+                       throw new MetadataParseException("Do not support DBRs 
pending decision on putting them in the key!");
+               }
+               
+               if(extraMetadata) {
+                       int numberOfExtraFields = (dis.readShort()) & 0xffff;
+                       for(int i=0;i<numberOfExtraFields;i++) {
+                               short type = dis.readShort();
+                               int len = (dis.readByte() & 0xff);
+                               byte[] buf = new byte[len];
+                               dis.readFully(buf);
+                               Logger.normal(this, "Ignoring type "+type+" 
extra-client-metadata field of "+length+" bytes");
+                       }
+               }
+               
+               if((!splitfile) && documentType == SIMPLE_REDIRECT || 
documentType == ZIP_MANIFEST) {
+                       simpleRedirectKey = readKey(dis);
+               } else if(splitfile) {
+                       splitfileAlgorithm = dis.readShort();
+                       if(!(splitfileAlgorithm == SPLITFILE_NONREDUNDANT ||
+                                       splitfileAlgorithm == 
SPLITFILE_ONION_STANDARD))
+                               throw new MetadataParseException("Unknown 
splitfile algorithm "+splitfileAlgorithm);
+                       
+                       if(splitfileAlgorithm == SPLITFILE_NONREDUNDANT &&
+                                       !(fullKeys || splitUseLengths))
+                               throw new MetadataParseException("Non-redundant 
splitfile invalid unless whacky");
+                       
+                       int paramsLength = dis.readInt();
+                       if(paramsLength > MAX_SPLITFILE_PARAMS_LENGTH)
+                               throw new MetadataParseException("Too many 
bytes of splitfile parameters: "+paramsLength);
+                       
+                       if(paramsLength > 0) {
+                               splitfileParams = new byte[paramsLength];
+                               dis.readFully(splitfileParams);
+                       } else if(paramsLength < 0) {
+                               throw new MetadataParseException("Invalid 
splitfile params length: "+paramsLength);
+                       }
+                       
+                       splitfileBlocks = dis.readInt(); // 64TB file size 
limit :)
+                       if(splitfileBlocks < 0)
+                               throw new MetadataParseException("Invalid 
number of blocks: "+splitfileBlocks);
+                       if(splitfileBlocks > MAX_SPLITFILE_BLOCKS)
+                               throw new MetadataParseException("Too many 
splitfile blocks (soft limit to prevent memory DoS): "+splitfileBlocks);
+                       splitfileCheckBlocks = dis.readInt();
+                       if(splitfileCheckBlocks < 0)
+                               throw new MetadataParseException("Invalid 
number of check blocks: "+splitfileCheckBlocks);
+                       if(splitfileCheckBlocks > MAX_SPLITFILE_BLOCKS)
+                               throw new MetadataParseException("Too many 
splitfile check-blocks (soft limit to prevent memory DoS): 
"+splitfileCheckBlocks);
+                       
+                       splitfileDataKeys = new FreenetURI[splitfileBlocks];
+                       splitfileCheckKeys = new 
FreenetURI[splitfileCheckBlocks];
+                       for(int i=0;i<splitfileDataKeys.length;i++)
+                               splitfileDataKeys[i] = readKey(dis);
+                       for(int i=0;i<splitfileCheckKeys.length;i++)
+                               splitfileCheckKeys[i] = readKey(dis);
+               }
+               
+               if(documentType == SIMPLE_MANIFEST) {
+                       manifestEntryCount = dis.readInt();
+                       if(manifestEntryCount < 0)
+                               throw new MetadataParseException("Invalid 
manifest entry count: "+manifestEntryCount);
+                       
+                       manifestEntries = new HashMap();
+                       
+                       // Don't validate, just keep the data; parse later
+                       
+                       for(int i=0;i<manifestEntryCount;i++) {
+                               int nameLength = (dis.readByte() & 0xff);
+                               byte[] buf = new byte[nameLength];
+                               dis.readFully(buf);
+                               String name = new String(buf, "UTF-8");
+                               int len = dis.readInt();
+                               if(len < 0)
+                                       throw new 
MetadataParseException("Invalid manifest entry size: "+len);
+                               if(len > length)
+                                       throw new 
MetadataParseException("Impossibly long manifest entry: "+len+" - metadata size 
"+length);
+                               byte[] data = new byte[len];
+                               dis.readFully(data);
+                               manifestEntries.put(name, data);
+                       }
+               }
+       }
+       
+       /**
+        * Read a key using the current settings.
+        */
+       private FreenetURI readKey(DataInputStream dis) {
+               // Read URL
+               if(fullKeys) {
+                       int length = (dis.readByte() & 0xff);
+                       byte[] buf = new byte[length];
+                       dis.readFully(buf);
+                       simpleRedirectKey = FreenetURI.fromFullBinaryKey(buf);
+               } else {
+                       simpleRedirectKey = 
ClientCHK.readRawBinaryKey(dis).getURI();
+               }
+       }
+
+       // Actual parsed data
+       
+       // document type
+       byte documentType;
+       static final byte SIMPLE_REDIRECT = 0;
+       static final byte MULTI_LEVEL_METADATA = 1;
+       static final byte SIMPLE_MANIFEST = 2;
+       static final byte ZIP_MANIFEST = 3;
+       static final byte ZIP_INTERNAL_REDIRECT = 4;
+       
+       // 2 bytes of flags
+       /** Is a splitfile */
+       boolean splitfile;
+       /** Is a DBR */
+       boolean dbr;
+       /** No MIME type */
+       boolean noMIME;
+       /** Compressed MIME type */
+       boolean compressedMIME;
+       /** Has extra client-metadata */
+       boolean extraMetadata;
+       /** Keys stored in full (otherwise assumed to be CHKs) */
+       boolean fullKeys;
+       /** Non-final splitfile chunks can be non-full */
+       boolean splitUseLengths;
+       /** Compressed splitfile */
+       boolean compressed;
+       static final short FLAGS_SPLITFILE = 1;
+       static final short FLAGS_DBR = 2;
+       static final short FLAGS_NO_MIME = 4;
+       static final short FLAGS_COMPRESSED_MIME = 8;
+       static final short FLAGS_EXTRA_METADATA = 16;
+       static final short FLAGS_FULL_KEYS = 32;
+       static final short FLAGS_SPLIT_USE_LENGTHS = 64;
+       static final short FLAGS_COMPRESSED = 128;
+       
+       /** ZIP manifest archive type */
+       short archiveType;
+       static final short ARCHIVE_ZIP = 0;
+       static final short ARCHIVE_TAR = 1; // FIXME for future use
+       
+       /** Compressed splitfile codec */
+       short compressionCodec;
+       static final short COMPRESS_GZIP = 0;
+       static final short COMPRESS_BZIP2 = 1; // FIXME for future use
+       
+       /** The length of the splitfile */
+       long dataLength;
+       /** The decompressed length of the compressed data */
+       long decompressedLength;
+       
+       /** The MIME type, as a string */
+       String mimeType;
+       
+       /** The compressed MIME type - lookup index for the MIME types table.
+        * Must be between 0 and 32767.
+        */
+       short compressedMIMEValue;
+       boolean hasCompressedMIMEParams;
+       short compressedMIMEParams;
+       
+       /** The simple redirect key */
+       FreenetURI simpleRedirectKey;
+       
+       short splitfileAlgorithm;
+       static final short SPLITFILE_NONREDUNDANT = 0;
+       static final short SPLITFILE_ONION_STANDARD = 1;
+       
+       /** Splitfile parameters */
+       byte[] splitfileParams;
+       int splitfileBlocks;
+       int splitfileCheckBlocks;
+       FreenetURI[] splitfileDataKeys;
+       FreenetURI[] splitfileCheckKeys;
+       
+       // Manifests
+       int manifestEntryCount;
+       /** Manifest entries by name */
+       HashMap manifestEntries;
+}

Added: trunk/freenet/src/freenet/client/MetadataParseException.java
===================================================================
--- trunk/freenet/src/freenet/client/MetadataParseException.java        
2005-10-22 18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/client/MetadataParseException.java        
2005-10-22 18:51:03 UTC (rev 7447)
@@ -0,0 +1,12 @@
+package freenet.client;
+
+import java.io.IOException;
+
+/** Thrown when Metadata parse fails. */
+public class MetadataParseException extends IOException {
+
+       public MetadataParseException(String string) {
+               super(string);
+       }
+
+}

Modified: trunk/freenet/src/freenet/keys/CHKBlock.java
===================================================================
--- trunk/freenet/src/freenet/keys/CHKBlock.java        2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/keys/CHKBlock.java        2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -18,7 +18,7 @@
  * CHK plus data. When fed a ClientCHK, can decode into the original
  * data for a client.
  */
-public class CHKBlock {
+public class CHKBlock implements KeyBlock {

     final byte[] data;
     final byte[] header;

Added: trunk/freenet/src/freenet/keys/ClientBlock.java
===================================================================
--- trunk/freenet/src/freenet/keys/ClientBlock.java     2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/keys/ClientBlock.java     2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -0,0 +1,5 @@
+package freenet.keys;
+
+public class ClientBlock {
+
+}

Modified: trunk/freenet/src/freenet/keys/ClientCHK.java
===================================================================
--- trunk/freenet/src/freenet/keys/ClientCHK.java       2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/keys/ClientCHK.java       2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -8,7 +8,7 @@
  * Client level CHK. Can be converted into a FreenetURI, can be used to decrypt
  * a CHKBlock, can be produced by a CHKBlock. 
  */
-public class ClientCHK {
+public class ClientCHK extends ClientKey {

     NodeCHK nodeKey;


Added: trunk/freenet/src/freenet/keys/ClientKey.java
===================================================================
--- trunk/freenet/src/freenet/keys/ClientKey.java       2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/keys/ClientKey.java       2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -0,0 +1,19 @@
+package freenet.keys;
+
+/**
+ * Base class for client keys.
+ * Client keys are decodable. Node keys are not.
+ */
+public abstract class ClientKey {
+
+       public static ClientKey get(FreenetURI origURI) {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+       /**
+        * Does the key contain metadata? If not, it contains real data.
+        */
+       public abstract boolean isMetadata();
+
+}

Modified: trunk/freenet/src/freenet/keys/Key.java
===================================================================
--- trunk/freenet/src/freenet/keys/Key.java     2005-10-22 18:24:08 UTC (rev 
7446)
+++ trunk/freenet/src/freenet/keys/Key.java     2005-10-22 18:51:03 UTC (rev 
7447)
@@ -9,7 +9,7 @@
 /**
  * @author amphibian
  * 
- * Base class for keys.
+ * Base class for node keys.
  */
 public abstract class Key implements WritableToDataOutputStream {


Added: trunk/freenet/src/freenet/keys/KeyBlock.java
===================================================================
--- trunk/freenet/src/freenet/keys/KeyBlock.java        2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/keys/KeyBlock.java        2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -0,0 +1,11 @@
+package freenet.keys;
+
+/**
+ * Interface for fetched blocks. Can be decoded with a key.
+ */
+public interface KeyBlock {
+
+       /** Decode with the key */
+       byte[] decode(ClientKey key);
+
+}

Modified: trunk/freenet/src/freenet/node/SimpleLowLevelClient.java
===================================================================
--- trunk/freenet/src/freenet/node/SimpleLowLevelClient.java    2005-10-22 
18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/node/SimpleLowLevelClient.java    2005-10-22 
18:51:03 UTC (rev 7447)
@@ -1,8 +1,11 @@
 package freenet.node;

+import freenet.keys.ClientBlock;
 import freenet.keys.ClientCHK;
 import freenet.keys.ClientCHKBlock;
+import freenet.keys.ClientKey;
 import freenet.keys.ClientPublishStreamKey;
+import freenet.keys.KeyBlock;

 /**
  * @author amphibian
@@ -17,7 +20,7 @@
     /**
      * Fetch a key. Return null if cannot retrieve it.
      */
-    public ClientCHKBlock getCHK(ClientCHK key);
+    public KeyBlock getKey(ClientKey key);

     /**
      * Insert a key.

Added: trunk/freenet/src/freenet/support/Bucket.java
===================================================================
--- trunk/freenet/src/freenet/support/Bucket.java       2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/support/Bucket.java       2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -0,0 +1,43 @@
+package freenet.support;
+import java.io.*;
+/**
+ * A bucket is any arbitrary object can temporarily store data.
+ * 
+ * @author oskar
+ */
+public interface Bucket {
+
+    /**
+     * Returns an OutputStream that is used to put data in this Bucket.
+     */
+    public OutputStream getOutputStream() throws IOException;
+
+    /**
+     * Returns an InputStream that reads data from this Bucket. If there is
+     * no data in this bucket, null is returned.
+     */
+    public InputStream getInputStream() throws IOException;
+
+    /**
+     * Returns a name for the bucket, may be used to identify them in
+     * certain in certain situations.
+     */
+    public String getName();
+
+    /**
+     * If resetWrite() is called on the object, the next getOutputStream
+     * should overwrite any other data in the bucket from the beginning,
+     * otherwise it should append it.
+     */
+    public void resetWrite() throws IOException;
+
+    /**
+     * Returns the amount of data currently in this bucket.
+     */
+    public long size();
+
+}
+
+
+
+

Added: trunk/freenet/src/freenet/support/BucketFactory.java
===================================================================
--- trunk/freenet/src/freenet/support/BucketFactory.java        2005-10-22 
18:24:08 UTC (rev 7446)
+++ trunk/freenet/src/freenet/support/BucketFactory.java        2005-10-22 
18:51:03 UTC (rev 7447)
@@ -0,0 +1,10 @@
+package freenet.support;
+
+import java.io.IOException;
+
+public interface BucketFactory {
+    public Bucket makeBucket(long size) throws IOException;
+    public Bucket makeImmutableBucket(byte[] data) throws IOException;
+    public void freeBucket(Bucket b) throws IOException;
+}
+

Added: trunk/freenet/src/freenet/support/LRUHashtable.java
===================================================================
--- trunk/freenet/src/freenet/support/LRUHashtable.java 2005-10-22 18:24:08 UTC 
(rev 7446)
+++ trunk/freenet/src/freenet/support/LRUHashtable.java 2005-10-22 18:51:03 UTC 
(rev 7447)
@@ -0,0 +1,105 @@
+package freenet.support;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+public class LRUHashtable {
+
+    /*
+     * I've just converted this to using the DLList and Hashtable
+     * this makes it Hashtable time instead of O(N) for push and
+     * remove, and Hashtable time instead of O(1) for pop.  Since
+     * push is by far the most done operation, this should be an
+     * overall improvement.
+     */
+    private final DoublyLinkedListImpl list = new DoublyLinkedListImpl();
+    private final Hashtable hash = new Hashtable();
+    
+    /**
+     *       push()ing an object that is already in
+     *       the queue moves that object to the most
+     *       recently used position, but doesn't add
+     *       a duplicate entry in the queue.
+     */
+    public final synchronized void push(Object key, Object value) {
+        QItem insert = (QItem)hash.get(key);
+        if (insert == null) {
+            insert = new QItem(key, value);
+            hash.put(key,insert);
+        } else {
+               insert.value = value;
+            list.remove(insert);
+        }
+
+        list.unshift(insert);
+    } 
+
+    /**
+     *  @return Least recently pushed Object.
+     */
+    public final synchronized Object popKey() {
+        if ( list.size() > 0 ) {
+            return ((QItem)hash.remove(((QItem)list.pop()).obj)).obj;
+        } else {
+            return null;
+        }
+    }
+
+    public final int size() {
+        return list.size();
+    }
+    
+    public final synchronized boolean removeKey(Object key) {
+       QItem i = (QItem)(hash.remove(key));
+       if(i != null) {
+           list.remove(i);
+           return true;
+       } else {
+           return false;
+       }
+    }
+    
+    /**
+     * Check if this queue contains obj
+     * @param obj Object to match
+     * @return true if this queue contains obj.
+     */
+    public final synchronized boolean containsKey(Object key) {
+        return hash.containsKey(key);
+    }
+    
+    /**
+     * Note that this does not automatically promote the key. You have
+     * to do that by hand with push(key, value).
+     */
+    public final synchronized Object get(Object key) {
+       QItem q = (QItem) hash.get(key);
+       if(q == null) return null;
+       return q.value;
+    }
+    
+    public Enumeration keys() {
+        return new ItemEnumeration();
+    }
+
+    private class ItemEnumeration implements Enumeration {
+        private Enumeration source = list.reverseElements();
+       
+        public boolean hasMoreElements() {
+            return source.hasMoreElements();
+        }
+
+        public Object nextElement() {
+            return ((QItem) source.nextElement()).obj;
+        }
+    }
+
+    private static class QItem extends DoublyLinkedListImpl.Item {
+        public Object obj;
+        public Object value;
+
+        public QItem(Object obj, Object key) {
+            this.obj = obj;
+        }
+    }
+}


Reply via email to