Last active
August 29, 2015 14:01
-
-
Save Bombe/6ba2d4eea79239557363 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/README.building.md b/README.building.md | |
| index c259e48..da274e2 100644 | |
| --- a/README.building.md | |
| +++ b/README.building.md | |
| @@ -2,7 +2,7 @@ | |
| Install junit 3 and Apache ant. For Debian Wheezy these are `junit` and `ant`. | |
| -* `lib/bcprov.jar`: Download Bouncy Castle 1.49: `wget --no-passive-ftp ftp://ftp.bouncycastle.org/pub/release1.49/bcprov-jdk15on-149.jar` (1.50 breaks something currently) | |
| +* `lib/bcprov.jar`: Download Bouncy Castle 1.49 (1.50 breaks something currently): `wget --no-passive-ftp ftp://ftp.bouncycastle.org/pub/release1.49/bcprov-jdk15on-149.jar` or `wget http://www.bouncycastle.org/download/bcprov-jdk15on-149.jar` | |
| * `lib/freenet/freenet-ext.jar`: Build the `contrib/` submodule or [download](https://downloads.freenetproject.org/alpha/freenet-ext.jar) for convenience. | |
| The dependencies could also be copied from an existing Freenet installation. | |
| @@ -11,6 +11,19 @@ The dependencies could also be copied from an existing Freenet installation. | |
| You may want to use the command line git client, as people have sometimes had problems with the egit plugin for Eclipse. | |
| +#### Eclipse 4 #### | |
| + | |
| +Create a new project via the new _Java Project from Existing Ant Build File_, selecting the _build.xml_ in the local cloned repo. This will create a project _freenet-autodep_. Copy the _build-clean.xml_ to the Eclipse project folder. | |
| + | |
| +_Configure the Build Path_, removing the obsolete JRE_LIB link and | |
| +* _Add Library_ choosing a Java 7 _JRE System Library_ | |
| +* _Add Library_, choosing _JUnit_ | |
| +* _Add External Archive..._ lib/freenet/freenet-ext.jar | |
| +* _Add External Archive..._ lib/bcprov.jar | |
| + | |
| + | |
| +#### Older versions of Eclipse #### | |
| + | |
| You may need to add the two jars, and junit 3, to the build path for the project, although the .project might help with this. | |
| ### Building Freenet from source: Caveats | |
| diff --git a/build-clean.xml b/build-clean.xml | |
| index c4097d2..3bd485c 100644 | |
| --- a/build-clean.xml | |
| +++ b/build-clean.xml | |
| @@ -46,6 +46,14 @@ maintainers may prefer to use this instead of build.xml. | |
| <fileset dir="${pmd.dir}" erroronmissingdir="false" includes="lib/*.jar"/> | |
| </path> | |
| + <property environment="env"/> | |
| + <property name="keystore" value="${env.jarsignerStoreLocation}"/> | |
| + <property name="keystore_alias" value="${env.jarsignerAlias}"/> | |
| + <property name="keystore_pass" value="${env.jarsignerStorePassword}"/> | |
| + <property name="key_pass" value="${env.jarsignerCodeSigningKeyPassword}"/> | |
| + | |
| + <property name="jar.dst" value="${main.dst}/freenet.jar"/> | |
| + | |
| <assertions><enable/></assertions> | |
| <!-- set version string based on git-describe --> | |
| @@ -69,6 +77,13 @@ maintainers may prefer to use this instead of build.xml. | |
| <target name="dist" depends="clean-all, all" description="clean-build everything"/> | |
| + <target name="sign" description="Sign the distribution" depends="package"> | |
| + <echo message="Signing the distribution"/> | |
| + <signjar jar="${jar.dst}" strict="false" tsaurl="http://timestamp.comodoca.com/rfc3161" alias="${keystore_alias}" keystore="${keystore}" storepass="${keystore_pass}" keypass="${key_pass}" sigalg="SHA256withRSA" digestalg="SHA-256"/> | |
| + <!-- TODO: Should have strict="true", but it was introduced in Java 7, which we cannot yet require. --> | |
| + <verifyjar jar="${jar.dst}" alias="${keystore_alias}" keystore="${keystore}" storepass="${keystore_pass}" keypass="${key_pass}"/> | |
| + </target> | |
| + | |
| <target name="all" depends="package, doc, findbugs, pmd, cpd" description="build everything, incl. docs, GWT js"/> | |
| <target name="clean-all" depends="clean, clean-doc, clean-gjs" description="clean all build products, incl. docs, GWT js"/> | |
| @@ -100,7 +115,7 @@ maintainers may prefer to use this instead of build.xml. | |
| jvmargs="-Xmx1536m -XX:MaxPermSize=384m -XX:ReservedCodeCacheSize=128m" > | |
| <auxClasspath refid="lib.path" /> | |
| <sourcePath path="${main.src}" /> | |
| - <class location="${main.dst}/freenet.jar" /> | |
| + <class location="${jar.dst}" /> | |
| </findbugs> | |
| </target> | |
| @@ -264,7 +279,7 @@ maintainers may prefer to use this instead of build.xml. | |
| <map from="${lib.contrib.loc}/" to="${lib.contrib.dir.rel}/"/> | |
| <map from="${lib.loc}/" to=""/> | |
| </pathconvert> | |
| - <jar jarfile="${main.dst}/freenet.jar" basedir="${main.make}"> | |
| + <jar jarfile="${jar.dst}" basedir="${main.make}"> | |
| <manifest> | |
| <attribute name="Main-Class" value="freenet.node.Node"/> | |
| <attribute name="Required-Ext-Version" value="29"/> | |
| diff --git a/src/freenet/client/async/ClientRequestSchedulerBase.java b/src/freenet/client/async/ClientRequestSchedulerBase.java | |
| index 2ebb084..8c529c3 100644 | |
| --- a/src/freenet/client/async/ClientRequestSchedulerBase.java | |
| +++ b/src/freenet/client/async/ClientRequestSchedulerBase.java | |
| @@ -3,6 +3,8 @@ | |
| * http://www.gnu.org/ for further details of the GPL. */ | |
| package freenet.client.async; | |
| +import static java.lang.String.format; | |
| + | |
| import java.security.MessageDigest; | |
| import java.util.ArrayList; | |
| import java.util.Iterator; | |
| @@ -386,11 +388,7 @@ abstract class ClientRequestSchedulerBase { | |
| if(listener.handleBlock(key, saltedKey, block, container, context)) | |
| ret = true; | |
| } catch (Throwable t) { | |
| - try { | |
| - Logger.error(this, "Caught "+t+" in handleBlock callback for "+listener, new Exception("error")); | |
| - } catch (Throwable t1) { | |
| - Logger.error(this, "Caught "+t+" in handleBlock callback", new Exception("error")); | |
| - } | |
| + Logger.error(this, format("Error in handleBlock callback for %s", listener), t); | |
| } | |
| if(listener.isEmpty()) { | |
| synchronized(this) { | |
| diff --git a/src/freenet/client/filter/CSSTokenizerFilter.java b/src/freenet/client/filter/CSSTokenizerFilter.java | |
| index 738c96c..853b778 100644 | |
| --- a/src/freenet/client/filter/CSSTokenizerFilter.java | |
| +++ b/src/freenet/client/filter/CSSTokenizerFilter.java | |
| @@ -1687,11 +1687,12 @@ class CSSTokenizerFilter { | |
| char c; | |
| char quoting = 0; | |
| boolean escaping = false; | |
| + int bracketing = 0; | |
| boolean eatLF = false; | |
| int escapedDigits = 0; | |
| for(int i=0;i<selectorString.length();i++) { | |
| c = selectorString.charAt(i); | |
| - if(c == '+' && quoting == 0 && !escaping) { | |
| + if(c == '+' && quoting == 0 && !escaping && bracketing == 0) { | |
| if(index == -1 || index == i-1 && selector == ' ') { | |
| index = i; | |
| selector = c; | |
| @@ -1706,6 +1707,10 @@ class CSSTokenizerFilter { | |
| index = i; | |
| selector = c; | |
| } | |
| + } else if(c == '(' && quoting == 0 && !escaping) { | |
| + bracketing += 1; | |
| + } else if(c == ')' && quoting == 0 && !escaping) { | |
| + bracketing -= 1; | |
| } else if(c == '\'' && quoting == 0 && !escaping) { | |
| quoting = c; | |
| } else if(c == '\"' && quoting == 0 && !escaping) { | |
| @@ -1754,6 +1759,7 @@ class CSSTokenizerFilter { | |
| if(logDEBUG) Logger.debug(this, "index="+index+" quoting="+quoting+" selector="+selector+" for \""+selectorString+"\""); | |
| if(quoting != 0) return null; // Mismatched quotes | |
| + if(bracketing != 0) return null; // Mismatched brackets | |
| if(index == -1) | |
| return HTMLelementVerifier(selectorString); | |
| diff --git a/src/freenet/client/filter/ElementInfo.java b/src/freenet/client/filter/ElementInfo.java | |
| index 5fde995..1938383 100644 | |
| --- a/src/freenet/client/filter/ElementInfo.java | |
| +++ b/src/freenet/client/filter/ElementInfo.java | |
| @@ -121,6 +121,10 @@ public class ElementInfo { | |
| static { | |
| PSEUDOCLASS.add("first-child"); | |
| PSEUDOCLASS.add("last-child"); | |
| + PSEUDOCLASS.add("nth-child"); | |
| + PSEUDOCLASS.add("nth-last-child"); | |
| + PSEUDOCLASS.add("nth-of-type"); | |
| + PSEUDOCLASS.add("nth-last-of-type"); | |
| PSEUDOCLASS.add("link"); | |
| PSEUDOCLASS.add("visited"); | |
| PSEUDOCLASS.add("hover"); | |
| @@ -333,23 +337,33 @@ public class ElementInfo { | |
| return true; | |
| - else if(cname.indexOf("lang")!=-1) | |
| + else if(cname.indexOf("lang")!=-1 && LANGUAGES.contains(getPseudoClassArg(cname, "lang"))) | |
| { | |
| - int langIndex=cname.indexOf("lang"); | |
| - int firstIndex=cname.indexOf("("); | |
| - int secondIndex=cname.lastIndexOf(")"); | |
| - if(cname.substring(langIndex+4,firstIndex).trim().equals("") && cname.substring(0,langIndex).trim().equals("") && cname.substring(secondIndex+1,cname.length()).trim().equals("")) | |
| - { | |
| - String language=CSSTokenizerFilter.removeOuterQuotes(cname.substring(firstIndex+1,secondIndex).trim()); | |
| - | |
| - // FIXME accept unknown languages as long as they are [a-z-] | |
| - if(LANGUAGES.contains(language)) | |
| - return true; | |
| - } | |
| - | |
| + // FIXME accept unknown languages as long as they are [a-z-] | |
| + return true; | |
| } | |
| + else if(cname.indexOf("nth-child")!=-1 && FilterUtils.isNth(getPseudoClassArg(cname, "nth-child"))) | |
| + return true; | |
| + else if(cname.indexOf("nth-last-child")!=-1 && FilterUtils.isNth(getPseudoClassArg(cname, "nth-last-child"))) | |
| + return true; | |
| + else if(cname.indexOf("nth-of-type")!=-1 && FilterUtils.isNth(getPseudoClassArg(cname, "nth-of-type"))) | |
| + return true; | |
| + else if(cname.indexOf("nth-last-of-type")!=-1 && FilterUtils.isNth(getPseudoClassArg(cname, "nth-last-of-type"))) | |
| + return true; | |
| + | |
| return false; | |
| + } | |
| + public static String getPseudoClassArg(String cname, String cname_sans_arg) { | |
| + String arg=""; | |
| + int cnameIndex=cname.indexOf(cname_sans_arg); | |
| + int firstIndex=cname.indexOf("("); | |
| + int secondIndex=cname.lastIndexOf(")"); | |
| + if(cname.substring(cnameIndex+cname_sans_arg.length(),firstIndex).trim().equals("") && cname.substring(0,cnameIndex).trim().equals("") && cname.substring(secondIndex+1,cname.length()).trim().equals("")) | |
| + { | |
| + arg=CSSTokenizerFilter.removeOuterQuotes(cname.substring(firstIndex+1,secondIndex).trim()); | |
| + } | |
| + return arg; | |
| } | |
| /** Is the string valid and safe? | |
| diff --git a/src/freenet/client/filter/FilterUtils.java b/src/freenet/client/filter/FilterUtils.java | |
| index c39f738..7a6c61a 100644 | |
| --- a/src/freenet/client/filter/FilterUtils.java | |
| +++ b/src/freenet/client/filter/FilterUtils.java | |
| @@ -10,6 +10,8 @@ public class FilterUtils { | |
| static { | |
| Logger.registerClass(FilterUtils.class); | |
| } | |
| + | |
| + private final static int MAX_NTH = 999999; // Limit range of numbers allowed in isNth, due to incorrect behavior found in webkit based browsers. | |
| //Basic Data types | |
| public static boolean isInteger(String strValue) | |
| @@ -703,6 +705,50 @@ public class FilterUtils { | |
| } | |
| return true; | |
| } | |
| + public static boolean isIntegerInRange(String strValue, int min, int max) | |
| + { | |
| + try | |
| + { | |
| + // Strip any leading '+' character, because Integer.parseInt handles it differently between Java 6 (fails) and 7 (succeeds). | |
| + if(strValue.length()>1 && strValue.charAt(0)=='+' && Character.isDigit(strValue.charAt(1))) | |
| + { | |
| + strValue = strValue.substring(1,strValue.length()); | |
| + } | |
| + | |
| + int value = Integer.parseInt(strValue); | |
| + return (value>=min && value<=max); | |
| + } | |
| + catch(Exception e) | |
| + { | |
| + return false; | |
| + } | |
| + } | |
| + public static boolean isNth(String value) | |
| + { | |
| + if(value.equals("odd") || value.equals("even") || isIntegerInRange(value, -MAX_NTH, MAX_NTH)) | |
| + { | |
| + return true; | |
| + } | |
| + else | |
| + { | |
| + // Check if value has the form "an+b" - where a and b can be any in range integer. | |
| + int nIndex=value.indexOf("n"); | |
| + if(nIndex!=-1) | |
| + { | |
| + int aLength=nIndex; | |
| + if(aLength==0 || (aLength==1 && value.charAt(0)=='-') || isIntegerInRange(value.substring(0,aLength), -MAX_NTH, MAX_NTH)) | |
| + { | |
| + int bIndex=nIndex+1; | |
| + int bLength=value.length()-bIndex; | |
| + if(bLength==0 || ((value.charAt(bIndex)=='+' || value.charAt(bIndex)=='-') && isIntegerInRange(value.substring(bIndex,value.length()), -MAX_NTH, MAX_NTH))) | |
| + { | |
| + return true; | |
| + } | |
| + } | |
| + } | |
| + } | |
| + return false; | |
| + } | |
| // public static HTMLNode getHTMLNodeFromElement(Element node) | |
| // { | |
| // String[] propertyName=new String[node.getAttributes().size()]; | |
| diff --git a/src/freenet/client/filter/JPEGFilter.java b/src/freenet/client/filter/JPEGFilter.java | |
| index e64dca4..8644813 100644 | |
| --- a/src/freenet/client/filter/JPEGFilter.java | |
| +++ b/src/freenet/client/filter/JPEGFilter.java | |
| @@ -197,6 +197,7 @@ public class JPEGFilter implements ContentDataFilter { | |
| int extensionCode = dis.readUnsignedByte(); | |
| if(extensionCode == 0x10 || extensionCode == 0x11 || extensionCode == 0x13) { | |
| // Alternate thumbnail, perfectly valid | |
| + dos.write(extensionCode); | |
| skipRest(blockLength, countAtStart, cis, dis, dos, "thumbnail frame"); | |
| Logger.minor(this, "Thumbnail frame"); | |
| } else | |
| diff --git a/src/freenet/clients/http/WelcomeToadlet.java b/src/freenet/clients/http/WelcomeToadlet.java | |
| index 8e15496..b1cb00b 100644 | |
| --- a/src/freenet/clients/http/WelcomeToadlet.java | |
| +++ b/src/freenet/clients/http/WelcomeToadlet.java | |
| @@ -33,7 +33,9 @@ import freenet.support.MultiValueTable; | |
| import freenet.support.Logger.LogLevel; | |
| import freenet.support.api.Bucket; | |
| import freenet.support.api.HTTPRequest; | |
| +import freenet.support.io.Closer; | |
| import freenet.support.io.FileUtil; | |
| +import freenet.support.io.LineReadingInputStream; | |
| public class WelcomeToadlet extends Toadlet { | |
| @@ -287,8 +289,8 @@ public class WelcomeToadlet extends Toadlet { | |
| if (request.isParameterSet("latestlog")) { | |
| final File logs = new File(node.config.get("logger").getString("dirname") + File.separator + "freenet-latest.log"); | |
| - | |
| - this.writeTextReply(ctx, 200, "OK", FileUtil.readUTF(logs)); | |
| + String text = readLogTail(logs, 100000); | |
| + this.writeTextReply(ctx, 200, "OK", text); | |
| return; | |
| } else if (request.isParameterSet("terminated")) { | |
| if ((!request.isParameterSet("formPassword")) || !request.getParam("formPassword").equals(ctx.getFormPassword())) { | |
| @@ -505,14 +507,39 @@ public class WelcomeToadlet extends Toadlet { | |
| final File logs = new File("wrapper.log"); | |
| long logSize = logs.length(); | |
| if(logs.exists() && logs.isFile() && logs.canRead() && (logSize > 0)) { | |
| + HTMLNode logInfoboxContent = ctx.getPageMaker().getInfobox("infobox-info", "Current status", contentNode, "start-progress", true); | |
| + LineReadingInputStream logreader = null; | |
| try { | |
| - HTMLNode logInfoboxContent = ctx.getPageMaker().getInfobox("infobox-info", "Current status", contentNode, "start-progress", true); | |
| - boolean isShortFile = logSize < 2000; | |
| - String content = FileUtil.readUTF(logs, (isShortFile ? 0 : logSize - 2000)); | |
| - int eol = content.indexOf('\n'); | |
| - boolean shallStripFirstLine = (!isShortFile) && (eol > 0); | |
| - logInfoboxContent.addChild("%", content.substring((shallStripFirstLine ? eol + 1 : 0)).replaceAll("\n", "<br>\n")); | |
| + logreader = FileUtil.getLogTailReader(logs, 2000); | |
| + String line; | |
| + while ((line = logreader.readLine(100000, 200, true)) != null) { | |
| + logInfoboxContent.addChild("#", line); | |
| + logInfoboxContent.addChild("br"); | |
| + } | |
| } catch(IOException e) {} | |
| + finally { | |
| + Closer.close(logreader); | |
| + } | |
| + } | |
| + } | |
| + | |
| + /** | |
| + * Reads and returns the content of <code>logfile</code>. At most <code>byteLimit</code> | |
| + * bytes will be read. If <code>byteLimit</code> is less than the size of <code>logfile</code>, | |
| + * the first part of the file will be skipped. If this leaves a partial line at the beginning | |
| + * of the content to return, that partial line will also be skipped. | |
| + * @param logfile The file to read | |
| + * @param byteLimit The maximum number of bytes to read | |
| + * @return The trailing portion of the file | |
| + * @throws IOException if an I/O error occurs | |
| + */ | |
| + private static String readLogTail(File logfile, long byteLimit) throws IOException { | |
| + LineReadingInputStream stream = null; | |
| + try { | |
| + stream = FileUtil.getLogTailReader(logfile, byteLimit); | |
| + return FileUtil.readUTF(stream).toString(); | |
| + } finally { | |
| + Closer.close(stream); | |
| } | |
| } | |
| diff --git a/src/freenet/clients/http/staticfiles/defaultbookmarks.dat b/src/freenet/clients/http/staticfiles/defaultbookmarks.dat | |
| index 0893ee5..eebf44d 100644 | |
| --- a/src/freenet/clients/http/staticfiles/defaultbookmarks.dat | |
| +++ b/src/freenet/clients/http/staticfiles/defaultbookmarks.dat | |
| @@ -52,7 +52,7 @@ BookmarkCategory1.Content.Bookmark5.Description=L10N:Sone | |
| BookmarkCategory1.Content.Bookmark5.ShortDescription=L10N:Sone | |
| BookmarkCategory1.Content.Bookmark5.URI=USK@nwa8lHa271k2QvJ8aa0Ov7IHAV-DFOCFgmDt3X6BpCI,DuQSUZiI~agF8c-6tjsFFGuZ8eICrzWCILB60nT8KKo,AQACAAE/sone/61/ | |
| BookmarkCategory1.Content.Bookmark5.hasAnActivelink=true | |
| -BookmarkCategory1.Content.Bookmark6.URI=USK@e3myoFyp5avg6WYN16ImHri6J7Nj8980Fm~aQe4EX1U,QvbWT0ImE0TwLODTl7EoJx2NBnwDxTbLTE6zkB-eGPs,AQACAAE/jSite/20/ | |
| +BookmarkCategory1.Content.Bookmark6.URI=USK@1waTsw46L9-JEQ8yX1khjkfHcn--g0MlMsTlYHax9zQ,oYyxr5jyFnaTsVGDQWk9e3ddOWGKnqEASxAk08MHT2Y,AQACAAE/jSite/2/ | |
| BookmarkCategory1.Content.Bookmark6.Name=jSite | |
| BookmarkCategory1.Content.Bookmark6.Description=L10N:jSite | |
| BookmarkCategory1.Content.Bookmark6.ShortDescription=L10N:jSite | |
| diff --git a/src/freenet/l10n/BaseL10n.java b/src/freenet/l10n/BaseL10n.java | |
| index 8501382..fb86850 100644 | |
| --- a/src/freenet/l10n/BaseL10n.java | |
| +++ b/src/freenet/l10n/BaseL10n.java | |
| @@ -34,7 +34,10 @@ import freenet.support.io.FileUtil; | |
| */ | |
| public class BaseL10n { | |
| - /** @see "http://www.omniglot.com/language/names.htm" */ | |
| + /** | |
| + * @see "http://www.omniglot.com/language/names.htm" | |
| + * @see "http://loc.gov/standards/iso639-2/php/code_list.php" | |
| + */ | |
| public enum LANGUAGE { | |
| // Windows language codes must be preceded with WINDOWS and be in upper case hex, 4 digits. | |
| @@ -50,13 +53,14 @@ public class BaseL10n { | |
| ITALIAN("it", "Italiano", "ita", new String[] { "WINDOWS0410", "WINDOWS0810"}), | |
| NORWEGIAN("no", "Norsk", "nor", new String[] { "WINDOWS0414", "WINDOWS0814"}), | |
| POLISH("pl", "Polski", "pol", new String[] { "WINDOWS0415"}), | |
| - SWEDISH("se", "Svenska", "svk", new String[] { "WINDOWS041D", "WINDOWS081D"}), | |
| + SWEDISH("sv", "Svenska", "swe", new String[] { "WINDOWS041D", "WINDOWS081D"}), | |
| CHINESE("zh-cn", "中文(简体)", "chn", new String[] { "WINDOWS0804", "WINDOWS1004" }), | |
| // simplified chinese, used on mainland, Singapore and Malaysia | |
| CHINESE_TAIWAN("zh-tw", "中文(繁體)", "zh-tw", new String[] { "WINDOWS0404", "WINDOWS0C04", "WINDOWS1404" }), | |
| // traditional chinese, used in Taiwan, Hong Kong and Macau | |
| RUSSIAN("ru", "Русский", "rus", new String[] { "WINDOWS0419" }), // Just one variant for russian. Belorussian is separate, code page 423, speakers may or may not speak russian, I'm not including it. | |
| JAPANESE("ja", "日本語", "jpn", new String[] { "WINDOWS0411" }), | |
| + BRAZILIAN_PORTUGUESE("pt-br", "Português do Brasil", "pt-br", new String[] { "WINDOWS0416" }), | |
| UNLISTED("unlisted", "unlisted", "unlisted", new String[] {}); | |
| /** The identifier we use internally : MUST BE UNIQUE! */ | |
| public final String shortCode; | |
| diff --git a/src/freenet/node/Node.java b/src/freenet/node/Node.java | |
| index 04daf21..474f198 100644 | |
| --- a/src/freenet/node/Node.java | |
| +++ b/src/freenet/node/Node.java | |
| @@ -4152,19 +4152,34 @@ public class Node implements TimeSkewDetectorCallback { | |
| } | |
| } | |
| - public CHKStore getChkDatacache() { | |
| + CHKStore getChkDatacache() { | |
| return chkDatacache; | |
| } | |
| - public CHKStore getChkDatastore() { | |
| + CHKStore getChkDatastore() { | |
| return chkDatastore; | |
| } | |
| - public SSKStore getSskDatacache() { | |
| + SSKStore getSskDatacache() { | |
| return sskDatacache; | |
| } | |
| - public SSKStore getSskDatastore() { | |
| + SSKStore getSskDatastore() { | |
| return sskDatastore; | |
| } | |
| + CHKStore getChkSlashdotCache() { | |
| + return chkSlashdotcache; | |
| + } | |
| + | |
| + CHKStore getChkClientCache() { | |
| + return chkClientcache; | |
| + } | |
| + | |
| + SSKStore getSskSlashdotCache() { | |
| + return sskSlashdotcache; | |
| + } | |
| + | |
| + SSKStore getSskClientCache() { | |
| + return sskClientcache; | |
| + } | |
| /** | |
| * This method returns all statistics info for our data store stats table | |
| diff --git a/src/freenet/node/NodeStats.java b/src/freenet/node/NodeStats.java | |
| index a80bf67..4ee44ca 100644 | |
| --- a/src/freenet/node/NodeStats.java | |
| +++ b/src/freenet/node/NodeStats.java | |
| @@ -28,7 +28,7 @@ import freenet.node.RequestTracker.WaitingForSlots; | |
| import freenet.node.SecurityLevels.NETWORK_THREAT_LEVEL; | |
| import freenet.node.stats.StatsNotAvailableException; | |
| import freenet.node.stats.StoreLocationStats; | |
| -import freenet.store.CHKStore; | |
| +import freenet.store.StoreCallback; | |
| import freenet.support.HTMLNode; | |
| import freenet.support.Histogram2; | |
| import freenet.support.LogThresholdCallback; | |
| @@ -3352,7 +3352,7 @@ public class NodeStats implements Persistable, BlockTimeCallback { | |
| @Override | |
| public double distanceStats() throws StatsNotAvailableException { | |
| - return cappedDistance(avgSlashdotCacheCHKLocation, node.getChkDatacache()); | |
| + return cappedDistance(avgSlashdotCacheCHKLocation, node.getChkSlashdotCache()); | |
| } | |
| }; | |
| } | |
| @@ -3386,7 +3386,7 @@ public class NodeStats implements Persistable, BlockTimeCallback { | |
| @Override | |
| public double distanceStats() throws StatsNotAvailableException { | |
| - return cappedDistance(avgClientCacheCHKLocation, node.getChkDatacache()); | |
| + return cappedDistance(avgClientCacheCHKLocation, node.getChkClientCache()); | |
| } | |
| }; | |
| } | |
| @@ -3420,7 +3420,7 @@ public class NodeStats implements Persistable, BlockTimeCallback { | |
| @Override | |
| public double distanceStats() throws StatsNotAvailableException { | |
| - return cappedDistance(avgStoreSSKLocation, node.getChkDatastore()); | |
| + return cappedDistance(avgStoreSSKLocation, node.getSskDatastore()); | |
| } | |
| }; | |
| } | |
| @@ -3454,7 +3454,7 @@ public class NodeStats implements Persistable, BlockTimeCallback { | |
| @Override | |
| public double distanceStats() throws StatsNotAvailableException { | |
| - return cappedDistance(avgCacheSSKLocation, node.getChkDatacache()); | |
| + return cappedDistance(avgCacheSSKLocation, node.getSskDatacache()); | |
| } | |
| }; | |
| } | |
| @@ -3488,7 +3488,7 @@ public class NodeStats implements Persistable, BlockTimeCallback { | |
| @Override | |
| public double distanceStats() throws StatsNotAvailableException { | |
| - return cappedDistance(avgSlashdotCacheSSKLocation, node.getChkDatacache()); | |
| + return cappedDistance(avgSlashdotCacheSSKLocation, node.getSskSlashdotCache()); | |
| } | |
| }; | |
| } | |
| @@ -3522,13 +3522,13 @@ public class NodeStats implements Persistable, BlockTimeCallback { | |
| @Override | |
| public double distanceStats() throws StatsNotAvailableException { | |
| - return cappedDistance(avgClientCacheSSKLocation, node.getChkDatacache()); | |
| + return cappedDistance(avgClientCacheSSKLocation, node.getSskClientCache()); | |
| } | |
| }; | |
| } | |
| - private double cappedDistance(DecayingKeyspaceAverage avgLocation, CHKStore store) { | |
| + private double cappedDistance(DecayingKeyspaceAverage avgLocation, StoreCallback<?> store) { | |
| double cachePercent = 1.0 * avgLocation.countReports() / store.keyCount(); | |
| //Cap the reported value at 100%, as the decaying average does not account beyond that anyway. | |
| if (cachePercent > 1.0) { | |
| diff --git a/src/freenet/node/Version.java b/src/freenet/node/Version.java | |
| index f68389f..0d76d58 100644 | |
| --- a/src/freenet/node/Version.java | |
| +++ b/src/freenet/node/Version.java | |
| @@ -50,7 +50,7 @@ public class Version { | |
| public static final String protocolVersion = "1.0"; | |
| /** The build number of the current revision */ | |
| - private static final int buildNumber = 1459; | |
| + private static final int buildNumber = 1461; | |
| /** Oldest build of fred we will talk to *before* _cal */ | |
| private static final int oldLastGoodBuild = 1450; | |
| diff --git a/src/freenet/node/fcp/TestDDACompleteMessage.java b/src/freenet/node/fcp/TestDDACompleteMessage.java | |
| index 7c4b542..ff619aa 100644 | |
| --- a/src/freenet/node/fcp/TestDDACompleteMessage.java | |
| +++ b/src/freenet/node/fcp/TestDDACompleteMessage.java | |
| @@ -58,7 +58,8 @@ public class TestDDACompleteMessage extends FCPMessage { | |
| File maybeWrittenFile = checkJob.writeFilename; | |
| if (maybeWrittenFile.exists() && maybeWrittenFile.isFile() && maybeWrittenFile.canRead()) { | |
| try { | |
| - isWriteAllowed = checkJob.writeContent.equals(FileUtil.readUTF(maybeWrittenFile).trim()); | |
| + String existingContent = FileUtil.readUTF(maybeWrittenFile).toString().trim(); | |
| + isWriteAllowed = checkJob.writeContent.equals(existingContent); | |
| } catch (IOException e) { | |
| Logger.error(this, "Caught an IOE trying to read the file (" + maybeWrittenFile + ")! " + e.getMessage()); | |
| } | |
| diff --git a/src/freenet/pluginmanager/PluginManager.java b/src/freenet/pluginmanager/PluginManager.java | |
| index a4cf405..c0b2f82 100644 | |
| --- a/src/freenet/pluginmanager/PluginManager.java | |
| +++ b/src/freenet/pluginmanager/PluginManager.java | |
| @@ -1097,11 +1097,16 @@ public class PluginManager { | |
| static { | |
| try { | |
| addOfficialPlugin("Freemail", "communication", false, 15, true, new FreenetURI("CHK@6dfMgGf7YEfJhF0W~K0HUv0fnbuRwYH6iMqrLIbTI7k,huYBf8oBevwW6lRQnz-0jDP1dl5ej7FKeyVZ3CnH0Ec,AAMC--8/Freemail.jar"), true, false, false); | |
| - addOfficialPlugin("Freemail_wot", "communication", false, 23, false, new FreenetURI("CHK@RL2twhvr2E7snE~rB0pSRzs178d4AF4Js2C6finxw8Y,dOfAtMTqkxdR2yC8l0bp4B-PzwHWj-9hdXmhcFOgm8M,AAMC--8/Freemail_wot.jar")); | |
| + addOfficialPlugin("Freemail_wot", "communication", false, 24, false, new FreenetURI("CHK@3quK1QnUrXS1KqVrc87lAy87boNiNUt83RIza0eAfLQ,J4tzwpdDuJKZJV22r6nBPgO5CGAwCWP~p7Xt~kzCDKY,AAMC--8/Freemail_wot.jar")); | |
| addOfficialPlugin("HelloWorld", "example", false, new FreenetURI("CHK@ZdTXnWV-ikkt25-y8jmhlHjCY-nikDMQwcYlWHww5eg,Usq3uRHpHuIRmMRRlNQE7BNveO1NwNI7oNKdb7cowFM,AAIC--8/HelloWorld.jar"), false, false, true); | |
| addOfficialPlugin("HelloFCP", "example", false, new FreenetURI("CHK@0gtXJpw1QUJCmFOhoPRNqhsNbMtVw1CGVe46FUv7-e0,X8QqhtPkHoaFCUd89bgNaKxX1AV0WNBVf3sRgSF51-g,AAIC--8/HelloFCP.jar"), false, false, true); | |
| - addOfficialPlugin("JSTUN", "connectivity", true, 2, false, new FreenetURI("CHK@STQEzqyYLPtd4mCMIXO2HV38J6jG492hyPcEjTdc1oI,ojl4TCcJpJbo1OcO8nwPjycNCt1mn6zJq3lxCNExIHI,AAIC--8/JSTUN.jar")); | |
| - addOfficialPlugin("KeyUtils", "technical", false, 5020, false, new FreenetURI("CHK@llroMhtxumQZG1~3g3YEE8sK7ceJUIZ8Jl6Gqg~5RXk,CKf~Qxcf1ouLOIs3yjT7Re2DZ9GqGNC3HB-TiVEXgQ4,AAMC--8/KeyUtils.jar"), false, false, true); | |
| + /* | |
| + * TODO: Updating plugins required for connectivity is currently poorly defined. If the node refuses | |
| + * to load the old version that is now below the minimum and cannot connect without the plugin then | |
| + * it cannot download the new one and connectivity will remain broken. See https://bugs.freenetproject.org/view.php?id=4490 | |
| + */ | |
| + addOfficialPlugin("JSTUN", "connectivity", true, 2, false, new FreenetURI("CHK@USIujVBZaukbHyabPiPu7I6BtK4neW-Ky9J1hTBrcmY,FU9HCD5F4RZBwZLLUPKvS2U2Ts2dGiyoEiH-SGDQ9~U,AAMC--8/JSTUN.jar")); | |
| + addOfficialPlugin("KeyUtils", "technical", false, 5021, false, new FreenetURI("CHK@AJ4MTxURy0ouvGeVaHoCGh59K7rUHpH7EvKD4Yqy7sY,TwT~eA4MwSTniZXuSBps4VECy2y9fHtHEA~zT-KQKSk,AAMC--8/KeyUtils.jar"), false, false, true); | |
| addOfficialPlugin("MDNSDiscovery", "connectivity", false, 2, false, new FreenetURI("CHK@wPyhY61bsDM3OW6arFlxYX8~mBKjo~XtOTIAbT0dk88,Vr3MTAzkW5J28SJs2dTxkj6D4GVNm3u8GFsxJgzTL1M,AAIC--8/MDNSDiscovery.jar")); | |
| addOfficialPlugin("SNMP", "connectivity", false, new FreenetURI("CHK@EykJIv83UE291zONVzfXqyJYX5t66uCQJHkzQrB61MI,-npuolPZj1fcAWane2~qzRNEjKDERx52aQ5bC6NBQgw,AAIC--8/SNMP.jar"), false, false, true); | |
| addOfficialPlugin("TestGallery", "example", false, 1, false, new FreenetURI("CHK@LfJVh1EkCr4ry0yDW74vwxkX-3nkr~ztW2z0SUZHfC0,-mz7l39dC6n0RTUiSokjC~pUDO7PWZ89miYesKH0-WA,AAIC--8/TestGallery.jar"), false, true, false); | |
| @@ -1113,7 +1118,7 @@ public class PluginManager { | |
| addOfficialPlugin("Library", "index", false, 35, true, new FreenetURI("CHK@VhhWe6sT41pPei4SBwxcmRXrJpMfPDXTFhtJ4rFxfsk,MrPki7hU35x2MHvV~8am~CdF-B4xzqxjMwDtqFVYJLQ,AAMC--8/Library.jar")); | |
| addOfficialPlugin("Spider", "index", false, 51, false, new FreenetURI("CHK@CcJfB~uOTgbzdpVr8htrhLXs0uNsVW6KFRpEvHGjXDU,BPr2fm9Cq9gj7BQeJdLbkCmcmXRx-e-b6aerDzSK4zk,AAMC--8/Spider.jar"), false, false, true); | |
| addOfficialPlugin("WebOfTrust", "communication", false, 13, true, new FreenetURI("CHK@dSfeVmjFX15QVyFCTUQmZItrJi8XnoYpiapxLTxaQeg,wizfFOtkKSBEdjUYgjCUJczjl74r0CjRBfzvaRvKUMo,AAMC--8/WebOfTrust.jar"), false, false, false); | |
| - addOfficialPlugin("FlogHelper", "communication", false, 30, true, new FreenetURI("CHK@4Ey1hDbEPTTJ1AVKkrq3h0QaeMWFETzPaBYFkoauYvs,SNmqkFnxgOdy7Qu8vOoibQORJFIa8su1Hc3U9DRUa9E,AAMC--8/FlogHelper.jar"), false, false, false); | |
| + addOfficialPlugin("FlogHelper", "communication", false, 31, true, new FreenetURI("CHK@HHay15aKpO2W7zpLYeh7lYIyG56MPEIsnugwJNGVJ9s,krPxNuxG9~9grOm9y4V2gAo3dbhiW0EKIKeMLsk5ntY,AAMC--8/FlogHelper.jar"), false, false, false); | |
| } catch (MalformedURLException e) { | |
| throw new Error("Malformed hardcoded URL: "+e, e); | |
| } | |
| diff --git a/src/freenet/pluginmanager/PluginTalker.java b/src/freenet/pluginmanager/PluginTalker.java | |
| index a54a76a..b835623 100644 | |
| --- a/src/freenet/pluginmanager/PluginTalker.java | |
| +++ b/src/freenet/pluginmanager/PluginTalker.java | |
| @@ -60,7 +60,7 @@ public class PluginTalker { | |
| public void run() { | |
| sendSyncInternalOnly(plugparams, data2); | |
| } | |
| - }, "FCPPlugin talk runner for " + this); | |
| + }, "FCPPlugin talk runner for " + pluginName); | |
| } | |
| public void sendSyncInternalOnly(final SimpleFieldSet plugparams, final Bucket data2) { | |
| diff --git a/src/freenet/support/io/FileUtil.java b/src/freenet/support/io/FileUtil.java | |
| index 37f4056..7b37576 100644 | |
| --- a/src/freenet/support/io/FileUtil.java | |
| +++ b/src/freenet/support/io/FileUtil.java | |
| @@ -42,6 +42,41 @@ final public class FileUtil { | |
| private static final int BUFFER_SIZE = 32*1024; | |
| + /** | |
| + * Returns a line reading stream for the content of <code>logfile</code>. The stream will | |
| + * contain at most <code>byteLimit</code> bytes. If <code>byteLimit</code> is less than the | |
| + * size of <code>logfile</code>, the first part of the file will be skipped. If this leaves a | |
| + * partial line at the beginning of the content to read, that partial line will also be | |
| + * skipped. | |
| + * @param logfile The file to open | |
| + * @param byteLimit The maximum number of bytes to read | |
| + * @return A line reader for the trailing portion of the file | |
| + * @throws java.io.IOException if an I/O error occurs | |
| + */ | |
| + public static LineReadingInputStream getLogTailReader(File logfile, long byteLimit) throws IOException { | |
| + long length = logfile.length(); | |
| + long skip = 0; | |
| + if (length > byteLimit) { | |
| + skip = length - byteLimit; | |
| + } | |
| + | |
| + FileInputStream fis = null; | |
| + LineReadingInputStream lis = null; | |
| + try { | |
| + fis = new FileInputStream(logfile); | |
| + lis = new LineReadingInputStream(fis); | |
| + if (skip > 0) { | |
| + lis.skip(skip); | |
| + lis.readLine(100000, 200, true); | |
| + } | |
| + } catch (IOException e) { | |
| + Closer.close(lis); | |
| + Closer.close(fis); | |
| + throw e; | |
| + } | |
| + return lis; | |
| + } | |
| + | |
| public static enum OperatingSystem { | |
| Unknown(false, false, false), // Special-cased in filename sanitising code. | |
| MacOS(false, true, true), // OS/X in that it can run scripts. | |
| @@ -254,11 +289,26 @@ final public class FileUtil { | |
| return result; | |
| } | |
| - public static String readUTF(File file) throws FileNotFoundException, IOException { | |
| - return readUTF(file, 0); | |
| - } | |
| + /** | |
| + * Reads the entire content of a file as UTF-8 and returns it. | |
| + * @param file The file to read | |
| + * @return The content of <code>file</code> | |
| + * @throws FileNotFoundException if <code>file</code> cannot be opened | |
| + * @throws IOException if an I/O error occurs | |
| + */ | |
| + public static StringBuilder readUTF(File file) throws FileNotFoundException, IOException { | |
| + return readUTF(file, 0); | |
| + } | |
| - public static String readUTF(File file, long offset) throws FileNotFoundException, IOException { | |
| + /** | |
| + * Reads the content of a file as UTF-8, starting at a specified offset, and returns it. | |
| + * @param file The file to read | |
| + * @param offset The point in <code>file</code> at which to start reading | |
| + * @return The content of <code>file</code>, starting at <code>offset</code> | |
| + * @throws FileNotFoundException if <code>file</code> cannot be opened | |
| + * @throws IOException if an I/O error occurs | |
| + */ | |
| + public static StringBuilder readUTF(File file, long offset) throws FileNotFoundException, IOException { | |
| StringBuilder result = new StringBuilder(); | |
| FileInputStream fis = null; | |
| BufferedInputStream bis = null; | |
| @@ -282,7 +332,41 @@ final public class FileUtil { | |
| Closer.close(bis); | |
| Closer.close(fis); | |
| } | |
| - return result.toString(); | |
| + return result; | |
| + } | |
| + | |
| + /** | |
| + * Reads the entire content of a stream as UTF-8 and returns it. | |
| + * @param stream The stream to read | |
| + * @return The content of <code>stream</code> | |
| + * @throws IOException if an I/O error occurs | |
| + */ | |
| + public static StringBuilder readUTF(InputStream stream) throws IOException { | |
| + return readUTF(stream, 0); | |
| + } | |
| + | |
| + /** | |
| + * Reads the content of a stream as UTF-8, starting at a specified offset, and returns it. | |
| + * @param stream The stream to read | |
| + * @param offset The point in <code>stream</code> at which to start reading | |
| + * @return The content of <code>stream</code>, starting at <code>offset</code> | |
| + * @throws IOException if an I/O error occurs | |
| + */ | |
| + public static StringBuilder readUTF(InputStream stream, long offset) throws IOException { | |
| + StringBuilder result = new StringBuilder(); | |
| + skipFully(stream, offset); | |
| + InputStreamReader reader = null; | |
| + try { | |
| + reader = new InputStreamReader(stream, "UTF-8"); | |
| + char[] buf = new char[4096]; | |
| + int length = 0; | |
| + while((length = reader.read(buf)) > 0) { | |
| + result.append(buf, 0, length); | |
| + } | |
| + } finally { | |
| + Closer.close(reader); | |
| + } | |
| + return result; | |
| } | |
| /** | |
| diff --git a/src/freenet/support/io/TempBucketFactory.java b/src/freenet/support/io/TempBucketFactory.java | |
| index 8f0468f..0d31b44 100644 | |
| --- a/src/freenet/support/io/TempBucketFactory.java | |
| +++ b/src/freenet/support/io/TempBucketFactory.java | |
| @@ -210,7 +210,9 @@ public class TempBucketFactory implements BucketFactory { | |
| } | |
| private void _maybeMigrateRamBucket(long futureSize) throws IOException { | |
| - if(closed) throw new IOException("Already closed"); | |
| + if (closed) { | |
| + return; | |
| + } | |
| if(isRAMBucket()) { | |
| boolean shouldMigrate = false; | |
| boolean isOversized = false; | |
| diff --git a/test/freenet/client/filter/CSSParserTest.java b/test/freenet/client/filter/CSSParserTest.java | |
| index f389dc4..db30306 100644 | |
| --- a/test/freenet/client/filter/CSSParserTest.java | |
| +++ b/test/freenet/client/filter/CSSParserTest.java | |
| @@ -151,6 +151,84 @@ public class CSSParserTest extends TestCase { | |
| CSS2_BAD_SELECTOR.add("h1[foo=\"hello\\202\r\n\"] {}"); | |
| } | |
| + | |
| + /** CSS3 Selectors */ | |
| + private final static HashMap<String,String> CSS3_SELECTOR= new HashMap<String,String>(); | |
| + static | |
| + { | |
| + CSS3_SELECTOR.put("tr:nth-child(odd) { background-color: red; }","tr:nth-child(odd) { background-color: red; }"); | |
| + CSS3_SELECTOR.put("tr:nth-child(even) { background-color: yellow; }","tr:nth-child(even) { background-color: yellow; }"); | |
| + CSS3_SELECTOR.put("tr:nth-child(1) {}","tr:nth-child(1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(-1) {}","tr:nth-child(-1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(+1) {}","tr:nth-child(+1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(10) {}","tr:nth-child(10)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(100) {}","tr:nth-child(100)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(n) {}","tr:nth-child(n)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(-n) {}","tr:nth-child(-n)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(-n+1) {}","tr:nth-child(-n+1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(n-1) {}","tr:nth-child(n-1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(-n-1) {}","tr:nth-child(-n-1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(-2n+1) {}","tr:nth-child(-2n+1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(-2n-1) {}","tr:nth-child(-2n-1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(2n) {}","tr:nth-child(2n)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(10n) {}","tr:nth-child(10n)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(n+1) {}","tr:nth-child(n+1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(n+10) {}","tr:nth-child(n+10)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(2n+1) {}","tr:nth-child(2n+1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(2n-1) {}","tr:nth-child(2n-1)"); | |
| + CSS3_SELECTOR.put("tr:nth-child(999999) {}","tr:nth-child(999999)"); // FilterUtils.MAX_NTH | |
| + CSS3_SELECTOR.put("tr:nth-child(-999999) {}","tr:nth-child(-999999)"); // -FilterUtils.MAX_NTH | |
| + CSS3_SELECTOR.put("tr:nth-last-child(1) {}","tr:nth-last-child(1)"); | |
| + CSS3_SELECTOR.put("tr:nth-last-child(odd) {}","tr:nth-last-child(odd)"); | |
| + CSS3_SELECTOR.put("tr:nth-last-child(even) {}","tr:nth-last-child(even)"); | |
| + CSS3_SELECTOR.put("h1:nth-of-type(1) {}","h1:nth-of-type(1)"); | |
| + CSS3_SELECTOR.put("h1:nth-of-type(odd) {}","h1:nth-of-type(odd)"); | |
| + CSS3_SELECTOR.put("h1:nth-of-type(even) {}","h1:nth-of-type(even)"); | |
| + CSS3_SELECTOR.put("h1:nth-last-of-type(1) {}","h1:nth-last-of-type(1)"); | |
| + CSS3_SELECTOR.put("h1:nth-last-of-type(odd) {}","h1:nth-last-of-type(odd)"); | |
| + CSS3_SELECTOR.put("h1:nth-last-of-type(even) {}","h1:nth-last-of-type(even)"); | |
| + } | |
| + | |
| + private final static HashSet<String> CSS3_BAD_SELECTOR= new HashSet<String>(); | |
| + static | |
| + { | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child() {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(-) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(+) {}"); | |
| + // an+b only - allow nothing more. | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(2+n) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(2n+1+1) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(+-2n) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(-+2n) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(2n1) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(n3) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(n+n) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(2n+-1) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(2n-+1) {}"); | |
| + // Out of Integer range. | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(999999999999999) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(1000000) {}"); // FilterUtils.MAX_NTH + 1 | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(-1000000) {}"); // -FilterUtils.MAX_NTH - 1 | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(999999999999999n) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(n+999999999999999) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(999999999999999n+999999999999999) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(999999999999999n-999999999999999) {}"); | |
| + // Misbracketing. | |
| + CSS3_BAD_SELECTOR.add("h1:nth-of-type(1 {}"); | |
| + CSS3_BAD_SELECTOR.add("h1:nth-of-type(1)) {}"); | |
| + CSS3_BAD_SELECTOR.add("h1:nth-of-type((1) {}"); | |
| + CSS3_BAD_SELECTOR.add("h1:nth-of-type(n+1 {}"); | |
| + CSS3_BAD_SELECTOR.add("h1:nth-of-type(n+1)) {}"); | |
| + CSS3_BAD_SELECTOR.add("h1:nth-of-type((n+1) {}"); | |
| + CSS3_BAD_SELECTOR.add("h1:nth-of-type)n+1( {}"); | |
| + CSS3_BAD_SELECTOR.add("h1:nth-of-type)(n+1)( {}"); | |
| + // Invalid whitespace. | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(2 n) {}"); | |
| + // Whitespace not supported at all. | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child( n+2) {}"); | |
| + CSS3_BAD_SELECTOR.add("tr:nth-child(n + 2) {}"); | |
| + } | |
| + | |
| private static final String CSS_STRING_NEWLINES = "* { content: \"this string does not terminate\n}\nbody {\nbackground: url(http://www.google.co.uk/intl/en_uk/images/logo.gif); }\n\" }"; | |
| private static final String CSS_STRING_NEWLINESC = "* {}\nbody { }\n"; | |
| @@ -756,7 +834,7 @@ public class CSSParserTest extends TestCase { | |
| String key=itr.next().toString(); | |
| String value=CSS2_SELECTOR.get(key); | |
| System.err.println("Test "+(i++)+" : "+key+" -> "+value); | |
| - assertTrue("key="+key+" value="+filter(key)+"\" should be \""+value+"\"", filter(key).contains(value)); | |
| + assertTrue("key="+key+" value=\""+filter(key)+"\" should be \""+value+"\"", filter(key).contains(value)); | |
| } | |
| i=0; | |
| @@ -767,6 +845,26 @@ public class CSSParserTest extends TestCase { | |
| } | |
| + public void testCSS3Selector() throws IOException, URISyntaxException { | |
| + Collection<String> c = CSS3_SELECTOR.keySet(); | |
| + Iterator<String> itr = c.iterator(); | |
| + int i=0; | |
| + while(itr.hasNext()) | |
| + { | |
| + String key=itr.next().toString(); | |
| + String value=CSS3_SELECTOR.get(key); | |
| + System.err.println("CSS3 test"+(i++)+" : "+key+" -> "+value); | |
| + assertTrue("key="+key+" value=\""+filter(key)+"\" should be \""+value+"\"", filter(key).contains(value)); | |
| + } | |
| + | |
| + i=0; | |
| + for(String key : CSS3_BAD_SELECTOR) { | |
| + System.err.println("CSS3 bad selector test "+(i++)); | |
| + assertTrue("".equals(filter(key))); | |
| + } | |
| + | |
| + } | |
| + | |
| public void testNewlines() throws IOException, URISyntaxException { | |
| assertTrue("key=\""+CSS_STRING_NEWLINES+"\" value=\""+filter(CSS_STRING_NEWLINES)+"\" should be: \""+CSS_STRING_NEWLINESC+"\"", CSS_STRING_NEWLINESC.equals(filter(CSS_STRING_NEWLINES))); | |
| } | |
| diff --git a/test/freenet/client/filter/JPEGFilterTest.java b/test/freenet/client/filter/JPEGFilterTest.java | |
| new file mode 100644 | |
| index 0000000..57feabb | |
| --- /dev/null | |
| +++ b/test/freenet/client/filter/JPEGFilterTest.java | |
| @@ -0,0 +1,54 @@ | |
| +package freenet.client.filter; | |
| + | |
| +import java.io.ByteArrayInputStream; | |
| +import java.io.ByteArrayOutputStream; | |
| +import java.io.IOException; | |
| +import java.io.InputStream; | |
| +import java.io.OutputStream; | |
| +import java.util.Arrays; | |
| +import java.util.HashMap; | |
| + | |
| +import junit.framework.TestCase; | |
| + | |
| +/** | |
| + * Unit test for (parts of) {@link JPEGFilter}. | |
| + * | |
| + * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a> | |
| + */ | |
| +public class JPEGFilterTest extends TestCase { | |
| + | |
| + public void testThatAThumbnailExtensionCodeIsPreserved() throws IOException { | |
| + JPEGFilter jpegFilter = new JPEGFilter(true, true); | |
| + byte[] jpegFile = createValidJpegFileWithThumbnail(); | |
| + InputStream inputStream = new ByteArrayInputStream(jpegFile); | |
| + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | |
| + jpegFilter.readFilter(inputStream, outputStream, "UTF-8", new HashMap<String, String>(), new NullFilterCallback()); | |
| + byte[] filteredJpegFile = outputStream.toByteArray(); | |
| + assertTrue(Arrays.equals(jpegFile, filteredJpegFile)); | |
| + } | |
| + | |
| + private byte[] createValidJpegFileWithThumbnail() throws IOException { | |
| + ByteArrayOutputStream jpegFile = new ByteArrayOutputStream(); | |
| + writeStartOfImageMarker(jpegFile); | |
| + writeAppMarker(jpegFile, 0, new byte[]{0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); | |
| + writeAppMarker(jpegFile, 0, new byte[]{0x4a, 0x46, 0x58, 0x58, 0x00, 0x13, 0x01, 0x01, 0x00, 0x7f, 0x00}); | |
| + writeEndOfImageMarker(jpegFile); | |
| + return jpegFile.toByteArray(); | |
| + } | |
| + | |
| + private void writeStartOfImageMarker(OutputStream outputStream) throws IOException { | |
| + outputStream.write(new byte[]{(byte) 0xff, (byte) 0xd8}); | |
| + } | |
| + | |
| + private void writeAppMarker(OutputStream outputStream, int app, byte[] payload) throws IOException { | |
| + outputStream.write(new byte[]{(byte) 0xff, (byte) (0xe0 + app)}); | |
| + int payloadLengthIncludingLength = payload.length + 2; | |
| + outputStream.write(new byte[]{(byte) ((payloadLengthIncludingLength >> 8) & 0xff), (byte) (payloadLengthIncludingLength & 0xff)}); | |
| + outputStream.write(payload); | |
| + } | |
| + | |
| + private void writeEndOfImageMarker(ByteArrayOutputStream outputStream) throws IOException { | |
| + outputStream.write(new byte[]{(byte) 0xff, (byte) 0xd9}); | |
| + } | |
| + | |
| +} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment