Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions app/src/main/java/com/httrack/android/OptionValues.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

package com.httrack.android;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -103,6 +104,29 @@ public static boolean isAtMost(final String value, final long max) {
}
}

/** Lowest non-zero rate the engine takes for -%c, and the highest. */
private static final String MIN_RATE = "0.000001";

private static final String MAX_RATE = new BigDecimal(Float.MAX_VALUE)
.toPlainString();

/**
* The rate brought inside the range the engine accepts. The engine panics on
* a rate between zero and 0.000001 or above a float, and a zero means no
* limit, so it stays.
*
* @param value
* A value isDecimal accepted
* @return the value, or the nearest rate the engine takes
*/
public static String clampRate(final String value) {
final double rate = Double.parseDouble(value);
if (rate > 0 && rate < Double.parseDouble(MIN_RATE)) {
return MIN_RATE;
}
return rate > Float.MAX_VALUE ? MAX_RATE : value;
}

/**
* True if the value is at most max bytes of UTF-8. An engine buffer is a byte
* count, so a limit measured in characters lets a non-ASCII value through.
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/java/com/httrack/android/OptionsMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -1736,9 +1736,12 @@ public void emit(final List<String> commandline, final String value) {
* as a URL, which turns -r1.5 into an exclusion filter. */
/* Over the cap the engine refuses the command line or misreads the
* value, and no layout bounds these fields. */
/* A rate the engine refuses is clamped, because dropping it would leave
* the crawl with no rate limit at all. */
if (fraction ? OptionValues.isDecimal(value) : OptionValues.isAtMost(
value, max)) {
commandline.add("-" + option + value);
commandline.add(
"-" + option + (fraction ? OptionValues.clampRate(value) : value));
} else {
refused(commandline, value);
}
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ LOCAL_SRC_FILES := httrack/src/htscore.c httrack/src/htsparse.c \
httrack/src/htstools.c httrack/src/htswizard.c httrack/src/htsalias.c \
httrack/src/htsthread.c httrack/src/htsindex.c httrack/src/htsbauth.c \
httrack/src/htsbundle.c \
httrack/src/htsbase.c \
httrack/src/htsmd5.c httrack/src/htszlib.c httrack/src/htswrap.c \
httrack/src/htsconcat.c httrack/src/htsmodules.c \
httrack/src/htscharset.c httrack/src/punycode.c \
Expand Down Expand Up @@ -113,6 +114,8 @@ LOCAL_CFLAGS += -O3 -g3 -funwind-tables -fPIC \
-Wno-nested-externs \
-D_REENTRANT -DPIC -DANDROID -D_ANDROID -DHAVE_CONFIG_H -DINET6 -DHTS_INTERNAL_BUILD \
-DLIBHTTRACK_EXPORTS -DZLIB_CONST -DHTS_INTHASH_USES_MD5 -DLIBICONV_PLUG
# HTS_INTERNAL_BYTECODE shows the engine-only half of the headers to the library.
LOCAL_CFLAGS += -DHTS_INTERNAL_BYTECODE
# The app never asks the engine for a self-test. The sources are gone from
# LOCAL_SRC_FILES above too, because htsselftest_int.h #errors under this macro.
LOCAL_CFLAGS += -DHTS_NO_SELFTEST
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/jni/httrack
Submodule httrack updated 250 files
45 changes: 45 additions & 0 deletions app/src/test/java/com/httrack/android/NumericOptionValueTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,51 @@ public void aSizeTheEngineWouldPanicOnNeverReachesIt() {
}
}

/** The float option's own bounds, which the pinned engine enforces. */
private static final String MIN_RATE = "0.000001";

private static final String MAX_RATE =
"340282346638528859811704183484516925440";

/* The engine panics on a rate between zero and the floor, and on one above a
float, where it used to cast whatever it read. */
@Test
public void aRateTheEngineWouldPanicOnIsClampedToTheBound() {
final OptionMapper mapper = new SimpleOption(FLOAT_OPTION, true);
for (final String value : new String[] { "0.0000001", "0.0000000001",
"0.00000099" }) {
assertEquals("-" + FLOAT_OPTION + MIN_RATE, emit(mapper, value).get(0));
}
assertEquals("-" + FLOAT_OPTION + MAX_RATE,
emit(mapper, "99999999999999999999999999999999999999999").get(0));
}

/** A zero means no limit and the engine still takes it. */
@Test
public void aRateTheEngineTakesIsSentUnchanged() {
final OptionMapper mapper = new SimpleOption(FLOAT_OPTION, true);
for (final String value : new String[] { "0", "0.0", MIN_RATE, "0.5", "5.0",
"100" }) {
assertEquals("-" + FLOAT_OPTION + value, emit(mapper, value).get(0));
}
}

/* The bounds live in the engine, so read them back: a moved floor must fail
here rather than ship a rate the engine panics on. */
@Test
public void theClampedBoundsAreTheOnesTheEngineChecks() throws IOException {
final String main = TestSources
.read(TestSources.engineFile("src/htscoremain.c"));
final String gate = TestSources.balancedBlock(main,
TestSources.indexOf(main, "case 'c': {"));
assertTrue("the engine no longer bounds -" + FLOAT_OPTION + " at 1e-6",
gate.contains("v >= 1e-6f"));
assertTrue("the engine no longer bounds -" + FLOAT_OPTION + " at FLT_MAX",
gate.contains("v <= FLT_MAX"));
assertEquals(1e-6, Double.parseDouble(MIN_RATE), 0.0);
assertEquals(Float.MAX_VALUE, Double.parseDouble(MAX_RATE), 0.0);
}

@Test
public void isPositiveRejectsWhatIsDigitsAccepts() {
assertTrue(OptionValues.isDigits("0"));
Expand Down
Loading