Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77d03052a6 | ||
|
|
628fc70727 | ||
|
|
7ff60e9de7 | ||
|
|
4588831dcd | ||
|
|
adbc46a5b8 | ||
|
|
249b96b975 | ||
|
|
d8402d7ad2 | ||
|
|
b268caa220 | ||
|
|
fb59dd6aba | ||
|
|
ef100363a7 | ||
|
|
c3e1a202c1 | ||
|
|
f55f68c94e | ||
|
|
749de004c7 | ||
|
|
09e3e1f62b | ||
|
|
4364e6c93e | ||
|
|
35319c05be | ||
|
|
e4fbe856e5 | ||
|
|
4f49eec86b | ||
|
|
f8ed3e771f | ||
|
|
4231a141d3 | ||
|
|
314ee45350 | ||
|
|
54d93200a4 | ||
|
|
6e98e33495 | ||
|
|
67c4668a3b | ||
|
|
e6015e29bb | ||
|
|
ba53bca32e | ||
|
|
5b59cdb159 | ||
|
|
c520d81f6b | ||
|
|
0748fa44e9 | ||
|
|
0ced83ccfc | ||
|
|
171ffb0754 | ||
|
|
e12fe63246 | ||
|
|
ff266a0e61 | ||
|
|
dfc0efff3a | ||
|
|
a0622bcd04 | ||
|
|
f5fbd1a82e | ||
|
|
496e85a3ac | ||
|
|
d4b77e53dc | ||
|
|
507f3565e8 | ||
|
|
4df1434b56 | ||
|
|
d85d91f8c6 | ||
|
|
b16ffc7be2 | ||
|
|
defd6735f3 | ||
|
|
178f9156e5 | ||
|
|
ee5db0a9e6 | ||
|
|
edeada647c | ||
|
|
562f6790ec | ||
|
|
cbb2257847 | ||
|
|
0e95c58865 | ||
|
|
8184b45696 | ||
|
|
62ca6e087a | ||
|
|
7c6e5c3018 | ||
|
|
1878595043 | ||
|
|
057648e335 | ||
|
|
7a7206d7f1 | ||
|
|
e4df3b387c | ||
|
|
58ddc5a6b1 | ||
|
|
fb01ad6f65 | ||
|
|
1a211555d0 | ||
|
|
f2abfc36ef | ||
|
|
b2cd2a51d2 | ||
|
|
562cd1c867 | ||
|
|
a2a20ef684 | ||
|
|
bfe0a4a7f7 | ||
|
|
03c30e17ce | ||
|
|
1a45e0237b | ||
|
|
2a44dc1728 | ||
|
|
23e182281c | ||
|
|
3426ea35ea | ||
|
|
0274e016af | ||
|
|
22fcf9ffff |
3
.gitattributes
vendored
@@ -6,6 +6,3 @@
|
||||
# bash die on $'\r' on every line of them.
|
||||
*.test text eol=lf
|
||||
*.sh text eol=lf
|
||||
|
||||
# Scoped to this file so a union can never touch build logic.
|
||||
tests/tests-list.mk merge=union
|
||||
|
||||
2
.github/workflows/appstream-network.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
- name: Install appstreamcli
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends appstream
|
||||
appstreamcli --version
|
||||
|
||||
|
||||
192
.github/workflows/ci.yml
vendored
@@ -38,10 +38,11 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential clang autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev \
|
||||
appstream appstream-util
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
@@ -79,6 +80,27 @@ jobs:
|
||||
- name: Build
|
||||
run: make -j"$(nproc)"
|
||||
|
||||
# FTP_PASV is 1 in every build, so #if !FTP_PASV never reaches a compiler
|
||||
# and rots unnoticed (#1091). Compiling is all this proves; nothing runs it.
|
||||
- name: Compile the FTP active-mode branch
|
||||
run: |
|
||||
set -euo pipefail
|
||||
objs="src/libhttrack_la-htsftp.lo src/libhttrack_la-htsftp.o src/.libs/libhttrack_la-htsftp.o"
|
||||
# accept() marks active-mode code: absent from the object Build made,
|
||||
# present below. One-sided, it passes on a file that ignored the define.
|
||||
syms=$(nm --undefined-only src/.libs/libhttrack_la-htsftp.o)
|
||||
if grep -qw accept <<<"$syms"; then
|
||||
echo "::error::accept() is reachable with FTP_PASV=1; the marker no longer discriminates"
|
||||
exit 1
|
||||
fi
|
||||
rm -f $objs
|
||||
# Through CC: overriding CPPFLAGS would drop configure's
|
||||
# -D_FORTIFY_SOURCE and the object-size warnings that come with it.
|
||||
make -C src libhttrack_la-htsftp.lo CC="$CC -DFTP_PASV=0 -Werror"
|
||||
syms=$(nm --undefined-only src/.libs/libhttrack_la-htsftp.o)
|
||||
grep -qw accept <<<"$syms" || { echo "::error::-DFTP_PASV=0 built no active-mode code"; exit 1; }
|
||||
rm -f $objs
|
||||
|
||||
# A backstop only: tests/test-timeout.sh bounds each test, and a healthy run
|
||||
# is a minute here, two on macOS. Without it a stall ran to the job's 6h default.
|
||||
- name: Test
|
||||
@@ -107,7 +129,7 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev
|
||||
@@ -137,6 +159,108 @@ jobs:
|
||||
if: failure()
|
||||
run: cat tests/test-suite.log 2>/dev/null || true
|
||||
|
||||
# Reproduces the buildds that refuse TEST-NET-1 instead of dropping it, where
|
||||
# every fixture needing a stalled connect must skip rather than fail (#1108).
|
||||
hostile-network:
|
||||
name: build (network refuses TEST-NET-1)
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev iproute2
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
set -euo pipefail
|
||||
autoreconf -fi
|
||||
./configure
|
||||
|
||||
- name: Build
|
||||
run: make -j"$(nproc)"
|
||||
|
||||
- name: Test on a network that refuses TEST-NET-1
|
||||
timeout-minutes: 20
|
||||
run: |
|
||||
set -euo pipefail
|
||||
jobs=$(( $(nproc) * 2 )); [ "$jobs" -le 16 ] || jobs=16
|
||||
tools/hostile-net.sh make check -j"$jobs"
|
||||
# A refusal landing before connect() returns skips on the older probe
|
||||
# instead, leaving the settle this leg exists to guard unrun.
|
||||
cat tests/246_engine-connect-stop.log
|
||||
grep -q 'within 500 ms' tests/246_engine-connect-stop.log
|
||||
|
||||
- name: Print the test log on failure
|
||||
if: failure()
|
||||
run: cat tests/test-suite.log 2>/dev/null || true
|
||||
|
||||
# The Ubuntu buildds run a development release every runner above is well behind.
|
||||
# That gap is what shipped 3.49.18 broken on every Ubuntu architecture but
|
||||
# riscv64, when 25.10 made uutils the default coreutils (#1042).
|
||||
ubuntu-devel:
|
||||
name: build (Ubuntu devel, uutils coreutils)
|
||||
runs-on: ubuntu-24.04
|
||||
container: ubuntu:devel
|
||||
timeout-minutes: 40
|
||||
steps:
|
||||
# Before checkout: the container has no git, so submodules would be lost.
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
apt-get update
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev \
|
||||
git ca-certificates python3 procps
|
||||
|
||||
- name: Assert the coreutils dispatch on argv[0]
|
||||
# The property #1042 broke on, not the version banner, which uutils has
|
||||
# already reworded once. Without it the job quietly becomes a slower copy
|
||||
# of the one above.
|
||||
run: |
|
||||
set -euo pipefail
|
||||
ln -s "$(command -v sleep)" /tmp/not-a-coreutil
|
||||
if /tmp/not-a-coreutil 0; then
|
||||
echo "::error::coreutils here take any argv[0]; this image no longer guards uutils" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
set -euo pipefail
|
||||
autoreconf -fi
|
||||
./configure
|
||||
# A renamed dev package would disable a codec or TLS here, and the tests
|
||||
# that cover them would SKIP rather than fail.
|
||||
grep -q "define HTS_USEBROTLI 1" config.h
|
||||
grep -q "define HTS_USEZSTD 1" config.h
|
||||
grep -q "define HTS_USEOPENSSL 1" config.h
|
||||
|
||||
- name: Build
|
||||
run: make -j"$(nproc)"
|
||||
|
||||
- name: Test
|
||||
timeout-minutes: 25
|
||||
run: |
|
||||
set -euo pipefail
|
||||
jobs=$(( $(nproc) * 2 )); [ "$jobs" -le 16 ] || jobs=16
|
||||
make check -j"$jobs"
|
||||
|
||||
- name: Print the test log on failure
|
||||
if: failure()
|
||||
run: cat tests/test-suite.log 2>/dev/null || true
|
||||
|
||||
# Portability: build and test on macOS (Darwin/clang) on a native runner --
|
||||
# no VM. The tree has no __APPLE__ branches, so Darwin exercises the
|
||||
# generic-Unix path on a second libc and kernel. brew's openssl@3 is keg-only,
|
||||
@@ -231,7 +355,7 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev
|
||||
@@ -340,7 +464,7 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential gcc-multilib autoconf automake libtool \
|
||||
autoconf-archive zlib1g-dev:i386 libssl-dev:i386 \
|
||||
@@ -383,7 +507,7 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev
|
||||
@@ -438,7 +562,7 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential clang autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev
|
||||
@@ -487,7 +611,7 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential clang autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev
|
||||
@@ -510,6 +634,33 @@ jobs:
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: bash fuzz/run-fuzzers.sh fuzz check
|
||||
|
||||
# Catches #1030: the job above links ASan, whose runtime already defines the
|
||||
# sancov hooks the instrumentation calls, hiding a program left without one.
|
||||
fuzz-no-sanitizer:
|
||||
name: build (fuzzers, no sanitizer runtime, clang)
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential clang autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev
|
||||
|
||||
- name: Configure (fuzzers, static)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
autoreconf -fi
|
||||
./configure CC=clang --enable-fuzzers --disable-shared
|
||||
|
||||
- name: Build
|
||||
run: make -j"$(nproc)"
|
||||
|
||||
# Optional-dependency build: compile and test with HTTPS/OpenSSL disabled --
|
||||
# the configuration users on minimal systems build, and one libssl is not even
|
||||
# installed here so configure cannot silently re-enable it. The matrix above
|
||||
@@ -526,7 +677,7 @@ jobs:
|
||||
- name: Install build dependencies (no libssl)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive zlib1g-dev
|
||||
|
||||
@@ -563,7 +714,7 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev
|
||||
@@ -642,7 +793,7 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev
|
||||
@@ -702,20 +853,18 @@ jobs:
|
||||
src/webhttrack.in
|
||||
tests/*.sh
|
||||
tests/*.test
|
||||
tools/macos-app.sh
|
||||
tools/macos-bundle.sh
|
||||
tools/macos-release.sh
|
||||
tools/mkdeb.sh
|
||||
tools/*.sh
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Install linters
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
# noble ships shfmt 3.8.0 (universe), matching the pinned local dev
|
||||
# version; use it rather than fetching a release binary from github.com.
|
||||
sudo apt-get install -y --no-install-recommends shellcheck shfmt appstream
|
||||
sudo apt-get install -y --no-install-recommends shellcheck shfmt appstream \
|
||||
appstream-util
|
||||
shfmt --version
|
||||
appstreamcli --version
|
||||
|
||||
@@ -725,6 +874,11 @@ jobs:
|
||||
- name: shfmt
|
||||
run: shfmt -d -i 4 $SHELL_SCRIPTS
|
||||
|
||||
# A misnamed test falls outside the glob "make check" runs, so it goes
|
||||
# missing without failing anything.
|
||||
- name: test file names
|
||||
run: bash tests/check-test-names.sh
|
||||
|
||||
# MSBuild rejects a malformed .vcxproj with a bare MSB4025 and no build, so
|
||||
# catch it here in seconds rather than on a Windows runner minutes in.
|
||||
- name: XML well-formedness (MSBuild project files)
|
||||
@@ -742,6 +896,8 @@ jobs:
|
||||
set -euo pipefail
|
||||
appstreamcli validate --no-net --explain \
|
||||
html/server/div/com.httrack.WebHTTrack.metainfo.xml
|
||||
appstream-util validate-relax --nonet \
|
||||
html/server/div/com.httrack.WebHTTrack.metainfo.xml
|
||||
|
||||
# Check clang-format on CHANGED LINES ONLY. The engine predates clang-format
|
||||
# (it was shaped by an old Visual Studio formatter) and does not round-trip,
|
||||
@@ -763,7 +919,7 @@ jobs:
|
||||
| sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc >/dev/null
|
||||
echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" \
|
||||
| sudo tee /etc/apt/sources.list.d/llvm-19.list >/dev/null
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends clang-format-19
|
||||
# The clang-format-19 package ships the git-clang-format driver;
|
||||
# expose it unsuffixed so "git clang-format" finds it.
|
||||
|
||||
2
.github/workflows/codeql.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev
|
||||
|
||||
116
.github/workflows/cross-arch.yml
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
# Cross-compiles for the Debian architectures no GitHub runner exists for.
|
||||
# 3.49.17 failed on four of them at once and every failure was a compile or
|
||||
# assemble error that x86-64 and arm64 cannot produce, so the buildd was the
|
||||
# first thing to see the code.
|
||||
name: Cross-arch
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
# Least privilege: the workflow only needs to read the repo.
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Cancel superseded runs on the same branch or PR.
|
||||
concurrency:
|
||||
group: cross-arch-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
cross:
|
||||
name: cross (${{ matrix.arch }})
|
||||
runs-on: ubuntu-24.04
|
||||
# sid, not stable: the point is to predict what the sid buildds will say.
|
||||
container: debian:sid
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# arch selects the hardening flags, triplet is the toolchain prefix.
|
||||
# The first four are 3.49.17's failures.
|
||||
- { arch: armhf, triplet: arm-linux-gnueabihf }
|
||||
- { arch: powerpc, triplet: powerpc-linux-gnu }
|
||||
- { arch: hppa, triplet: hppa-linux-gnu }
|
||||
- { arch: loong64, triplet: loongarch64-linux-gnu }
|
||||
- { arch: sh4, triplet: sh4-linux-gnu }
|
||||
- { arch: m68k, triplet: m68k-linux-gnu }
|
||||
- { arch: sparc64, triplet: sparc64-linux-gnu }
|
||||
- { arch: riscv64, triplet: riscv64-linux-gnu }
|
||||
- { arch: s390x, triplet: s390x-linux-gnu }
|
||||
env:
|
||||
DEB_HOST_ARCH: ${{ matrix.arch }}
|
||||
TRIPLET: ${{ matrix.triplet }}
|
||||
ZPREFIX: /tmp/zlib-${{ matrix.arch }}
|
||||
steps:
|
||||
- name: Install the toolchain
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# deb-src, so zlib below comes from the archive and not a pinned URL.
|
||||
# In place: a second stanza has to repeat Signed-By, and apt rejects
|
||||
# the same source carrying two spellings of the keyring.
|
||||
sed -i 's/^Types: deb$/Types: deb deb-src/' \
|
||||
/etc/apt/sources.list.d/debian.sources
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive \
|
||||
dpkg-dev git ca-certificates \
|
||||
"gcc-$TRIPLET" "libc6-dev-$DEB_HOST_ARCH-cross"
|
||||
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Cross-build zlib
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Mandatory, and no ports arch has a zlib1g-dev:<arch> to
|
||||
# multiarch-install. -fPIC because libhttrack.so links it.
|
||||
mkdir -p /tmp/zsrc && cd /tmp/zsrc
|
||||
# Unpatched: Debian's arch-specific patches expect its own rules to
|
||||
# build them (s390x's vector CRC pulls a header they add), and we only
|
||||
# need something to link -lz against.
|
||||
apt-get source --download-only zlib1g
|
||||
dpkg-source --skip-patches -x ./*.dsc src
|
||||
cd src
|
||||
CHOST="$TRIPLET" CC="$TRIPLET-gcc" CFLAGS="-O2 -fPIC" \
|
||||
./configure --prefix="$ZPREFIX" --static
|
||||
# configure detects s390x's vector CRC, whose sources live in the
|
||||
# contrib/ the .dfsg repack drops: drop the define and the object it
|
||||
# would build. Nothing here needs a fast CRC.
|
||||
sed -i -E 's/(-DHAVE_S390X_VX|crc32_vx\.l?o)//g' Makefile
|
||||
make -j"$(nproc)"
|
||||
make install
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
set -euo pipefail
|
||||
autoreconf -fi
|
||||
mkdir -p /tmp/bld && cd /tmp/bld
|
||||
# The buildd's own per-arch flags: -D_FILE_OFFSET_BITS=64 is the shim
|
||||
# hazard, and -fstack-clash-protection is not offered everywhere.
|
||||
eval "$(dpkg-buildflags --export=sh)"
|
||||
# A cross AC_TRY_RUN answers "cross", which would swap in the bundled
|
||||
# snprintf that no buildd ever builds. Every glibc passes these.
|
||||
# --disable-https: no ports arch has a cross libssl, so the TLS paths
|
||||
# are the one part of the tree this matrix does not compile.
|
||||
"$GITHUB_WORKSPACE/configure" --host="$TRIPLET" \
|
||||
--build="$(dpkg-architecture -qDEB_BUILD_GNU_TYPE)" --disable-https \
|
||||
ac_cv_have_working_snprintf=yes ac_cv_have_working_vsnprintf=yes \
|
||||
CPPFLAGS="${CPPFLAGS:-} -I$ZPREFIX/include" \
|
||||
LDFLAGS="${LDFLAGS:-} -L$ZPREFIX/lib"
|
||||
|
||||
- name: Build
|
||||
run: make -C /tmp/bld -j"$(nproc)"
|
||||
|
||||
- name: Build the test artifacts
|
||||
# Nothing runs here, but the shims are where three of the four 3.49.17
|
||||
# failures were: they only build under `check`. Asserted, because an
|
||||
# empty TESTS= would otherwise pass having built nothing.
|
||||
run: |
|
||||
set -euo pipefail
|
||||
make -C /tmp/bld -j"$(nproc)" check TESTS=
|
||||
test -f /tmp/bld/tests/.libs/libaltstackprobe.so
|
||||
12
.github/workflows/screenshots.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get update || true # a third-party source in the runner image can 403 (#1097)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential autoconf automake libtool autoconf-archive \
|
||||
zlib1g-dev libssl-dev libbrotli-dev libzstd-dev
|
||||
@@ -52,6 +52,15 @@ jobs:
|
||||
pip install --quiet playwright
|
||||
playwright install --with-deps chromium
|
||||
|
||||
# The address is on screen in the wizard panes and names the mirror folder,
|
||||
# so the crawl needs a presentable host rather than 127.0.0.1 and a random
|
||||
# port. example.com is reserved for documentation (RFC 2606).
|
||||
- name: Let the crawl address a named site on port 80
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "127.0.0.1 www.example.com" | sudo tee -a /etc/hosts
|
||||
sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80 # bind 80 unprivileged
|
||||
|
||||
- name: Capture
|
||||
env:
|
||||
LANGN: ${{ inputs.lang || '1' }}
|
||||
@@ -61,6 +70,7 @@ jobs:
|
||||
# --root is the dist root; the source tree already holds every piece
|
||||
# htsserver reads, so this needs no install.
|
||||
python3 tools/screenshot-walk.py --htsserver src/htsserver --root . \
|
||||
--site-host www.example.com --site-port 80 \
|
||||
--lang "$LANGN" --scale "$SCALE" --out shots
|
||||
|
||||
- name: Upload the screens
|
||||
|
||||
14
.github/workflows/windows-build.yml
vendored
@@ -14,6 +14,9 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
# The suite watchdog reports as a commit status, the only channel that
|
||||
# outlives the runner it is reporting on (#795).
|
||||
statuses: write
|
||||
|
||||
# Cancel superseded runs on the same branch or PR.
|
||||
concurrency:
|
||||
@@ -37,6 +40,9 @@ jobs:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive # coucal lives in src/coucal
|
||||
# Or the job token stays in .git/config, where every test the suite
|
||||
# runs can read it.
|
||||
persist-credentials: false
|
||||
|
||||
# Located through vswhere rather than microsoft/setup-msbuild: the repo
|
||||
# only allows GitHub-owned actions.
|
||||
@@ -171,6 +177,14 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: tests
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
# Through the environment, never argv, which the process list exposes.
|
||||
WATCHDOG_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
WATCHDOG_REPO: ${{ github.repository }}
|
||||
# github.sha here is the PR's merge commit, so statuses posted against it stay out of the PR's checks UI.
|
||||
WATCHDOG_SHA: ${{ github.sha }}
|
||||
WATCHDOG_CONTEXT: windows-suite (${{ matrix.platform }}, ${{ matrix.configuration }})
|
||||
WATCHDOG_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
run: |
|
||||
bash ./ci-windows-suite.sh \
|
||||
"$(cygpath -u "$GITHUB_WORKSPACE")/src/${{ matrix.platform }}/${{ matrix.configuration }}"
|
||||
|
||||
18
AGENTS.md
@@ -19,8 +19,12 @@ the operational checklist: toolchain, invariants, and how to ship a change.
|
||||
(`request_queue_size`) so macOS/BSD don't drop connections under a parallel
|
||||
`-c16` bigcrawl the way Python's default backlog of 5 did.
|
||||
Or run `sh build.sh` to do bootstrap + configure + make in one shot.
|
||||
- A `tests/NN_*.test` runs only if listed in `tests/tests-list.mk`; an
|
||||
unregistered file is silently skipped.
|
||||
- `configure` globs `TESTS` from `tests/[0-9]*_*.test`, so a new test needs no
|
||||
registration, but an existing build dir keeps the list it was configured with:
|
||||
`231_test-names.test` goes red until you reconfigure. It also compares the glob
|
||||
against `git ls-files`, so a test you forgot to `git add` fails there instead of
|
||||
quietly shrinking CI's suite. Name one outside the pattern and it never runs;
|
||||
`tests/check-test-names.sh` (also a CI lint) rejects that.
|
||||
- `make check` prepends the build's `src/` to `PATH`, but a hand-run `.test` does
|
||||
not — an installed `/usr/bin/httrack` then shadows your build. Run via `make
|
||||
check`, or `PATH="<bld>/src:$PATH"` for a manual run.
|
||||
@@ -38,6 +42,16 @@ the operational checklist: toolchain, invariants, and how to ship a change.
|
||||
match that is not on the last line is exposed. Capture the reply, assert the
|
||||
status line it must carry (an empty, truncated or redirected one is
|
||||
marker-free too), then match with a here-string: `grep -q M <<<"$reply"`.
|
||||
`head -c N` and `head -n N` end the same way, and there the reds are
|
||||
platform-specific: GNU `tail | head -c 3` survives, the uutils coreutils leg
|
||||
turns the same line into exit 141 with no output at all. Let the reader seek
|
||||
instead: `od -An -c -j <skip> -N <len> file`.
|
||||
- Never assert a fault by signal *number*: SIGBUS is 7 on x86, arm, powerpc and
|
||||
s390x but 10 on hppa, alpha, mips and sparc. Map it with `kill -l "$n"`.
|
||||
- A fixture that needs a host to stay silent must settle (500ms), re-probe every
|
||||
socket, and SKIP when one answered: the powerpc and ppc64 buildds refuse
|
||||
TEST-NET-1 milliseconds after `connect()` where runners drop it.
|
||||
`tools/hostile-net.sh` runs a command on such a network.
|
||||
|
||||
## Hard invariants
|
||||
- **Generated autotools files are NOT in git.** `configure`, every
|
||||
|
||||
36
configure.ac
@@ -1,6 +1,6 @@
|
||||
AC_PREREQ([2.71])
|
||||
|
||||
AC_INIT([httrack], [3.49.17], [roche+packaging@httrack.com], [httrack], [http://www.httrack.com/])
|
||||
AC_INIT([httrack], [3.49.20], [roche+packaging@httrack.com], [httrack], [http://www.httrack.com/])
|
||||
AC_COPYRIGHT([
|
||||
HTTrack Website Copier, Offline Browser for Windows and Unix
|
||||
Copyright (C) 1998-2015 Xavier Roche and other contributors
|
||||
@@ -29,6 +29,13 @@ AC_CONFIG_SRCDIR(src/httrack.c)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
AM_INIT_AUTOMAKE([subdir-objects])
|
||||
# 3:13:0: revision-only bump. htsstrings.h's StringRoomTotal grew saturation in
|
||||
# its macro body; no installed struct moved and no export came or went.
|
||||
# 3:12:0: revision-only bump. httrackp gained a tail field (singlefile_state) and
|
||||
# htsopt.h added volatile qualifiers; no layout moved, nothing went away.
|
||||
# 3:11:0: revision-only bump. #1001 moved SOCaddr_inetntoa_ out of htsnet.h, adding
|
||||
# an export where callers had an inline; nothing changed or went away.
|
||||
# 3:10:0: revision-only bump; only the version macro moved, the engine is untouched.
|
||||
# 3:9:0: revision-only bump. #991 and #1005 each added an export
|
||||
# (hts_set_thread_hooks, escape_control_url); nothing changed or went away.
|
||||
# 3:8:0: revision-only bump, no ABI change.
|
||||
@@ -37,7 +44,7 @@ AM_INIT_AUTOMAKE([subdir-objects])
|
||||
# moves nothing). Soname stays .so.3: HTTrackQt is the only consumer of the installed
|
||||
# headers, so a libhttrack4 rename isn't worth it.
|
||||
# (3:0:0 was the htsblk mime-buffer widening, the ABI break that moved .so.2 -> .so.3.)
|
||||
VERSION_INFO="3:9:0"
|
||||
VERSION_INFO="3:13:0"
|
||||
AM_MAINTAINER_MODE
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
@@ -392,7 +399,10 @@ AC_CHECK_TYPE(sa_family_t, [], [AC_DEFINE([sa_family_t], [uint16_t], [sa_family_
|
||||
AX_CHECK_ALIGNED_ACCESS_REQUIRED
|
||||
|
||||
# check for various headers
|
||||
AC_CHECK_HEADERS([execinfo.h sys/ioctl.h])
|
||||
AC_CHECK_HEADERS([execinfo.h sys/ioctl.h sys/random.h])
|
||||
|
||||
## CSPRNG for the --single-file mark; /dev/urandom is the fallback
|
||||
AC_CHECK_FUNCS([getrandom])
|
||||
|
||||
### zlib (mandatory)
|
||||
CHECK_ZLIB()
|
||||
@@ -547,7 +557,7 @@ AC_DEFINE(HAVE_STRNLEN, 1,[Check for strnlen])], AC_MSG_RESULT([not found]))
|
||||
## Online unit tests
|
||||
AC_MSG_CHECKING(whether to enable online unit tests)
|
||||
AC_ARG_ENABLE([online-unit-tests],
|
||||
[AS_HELP_STRING([--enable-online-unit-tests=@<:@yes/no/auto@:>@],[Enable online-unit-tests @<:@default=yes@:>@])],
|
||||
[AS_HELP_STRING([--enable-online-unit-tests=@<:@yes/no/auto@:>@],[Enable online-unit-tests @<:@default=no@:>@])],
|
||||
[
|
||||
case "${enableval}" in
|
||||
no|yes|auto)
|
||||
@@ -589,6 +599,10 @@ if test x"$fuzzers" = x"yes"; then
|
||||
AX_CHECK_COMPILE_FLAG([-fsanitize=fuzzer-no-link],
|
||||
[DEFAULT_CFLAGS="$DEFAULT_CFLAGS -fsanitize=fuzzer-no-link"],
|
||||
[AC_MSG_ERROR([--enable-fuzzers requires libFuzzer support (clang)])])
|
||||
# Ordinary programs are instrumented too, so they need that runtime at link.
|
||||
AX_CHECK_LINK_FLAG([-fsanitize=fuzzer-no-link],
|
||||
[DEFAULT_LDFLAGS="$DEFAULT_LDFLAGS -fsanitize=fuzzer-no-link"],
|
||||
[AC_MSG_ERROR([--enable-fuzzers requires libFuzzer support (clang)])])
|
||||
# clang's static sanitizer runtimes clash with -Wl,--no-undefined on the .so.
|
||||
if test x"$enable_shared" != x"no"; then
|
||||
AC_MSG_ERROR([--enable-fuzzers requires --disable-shared])
|
||||
@@ -596,6 +610,20 @@ if test x"$fuzzers" = x"yes"; then
|
||||
fi
|
||||
AM_CONDITIONAL([FUZZERS], [test x"$fuzzers" = x"yes"])
|
||||
|
||||
# tests/Makefile.am takes its TESTS from here instead of a checked-in list,
|
||||
# which made every pair of test-adding PRs conflict on the forge (#844).
|
||||
AC_MSG_CHECKING([for test scripts])
|
||||
TESTS_LIST=
|
||||
hts_ntests=0
|
||||
for hts_t in "$srcdir"/tests/[[0-9]]*_*.test; do
|
||||
test -f "$hts_t" || continue
|
||||
TESTS_LIST="$TESTS_LIST `echo "$hts_t" | sed 's|.*/||'`"
|
||||
hts_ntests=`expr $hts_ntests + 1`
|
||||
done
|
||||
AC_SUBST([TESTS_LIST])
|
||||
AC_MSG_RESULT([$hts_ntests])
|
||||
test "$hts_ntests" -gt 0 || AC_MSG_ERROR([no test script matched tests/[[0-9]]*_*.test])
|
||||
|
||||
# Final output
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
|
||||
32
debian/changelog
vendored
@@ -1,3 +1,35 @@
|
||||
httrack (3.49.20-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release: an off-site link that looked like a file could pull
|
||||
in the whole foreign site, and a mirror asked to stop while receiving over
|
||||
FTP hung; full list in history.txt. The documentation was also refreshed.
|
||||
* debian/copyright: record the League Spartan webfont the documentation now
|
||||
bundles (OFL-1.1).
|
||||
|
||||
-- Xavier Roche <xavier@debian.org> Mon, 10 Aug 2026 21:08:40 +0200
|
||||
|
||||
httrack (3.49.19-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release: mostly FTP fixes, plus stack-overflow, mirror
|
||||
interruption and --update data-loss fixes; full list in history.txt. Two
|
||||
of them matter to the build: the test suite no longer assumes GNU
|
||||
coreutils, and the AppStream metainfo no longer declares a non-stock icon
|
||||
name that appstream-util rejects.
|
||||
|
||||
-- Xavier Roche <xavier@debian.org> Sat, 08 Aug 2026 21:29:56 +0200
|
||||
|
||||
httrack (3.49.18-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release, fixing the 3.49.17-1 build failures on armhf,
|
||||
powerpc, hppa and loong64: the test suite's mmap interposer did not
|
||||
compile on the first three, and the alternate-stack test insisted on a
|
||||
longer backtrace than loong64's unwinder produces. Nothing in the engine
|
||||
changed. Upstream now cross-builds the test shims for the ports
|
||||
architectures on every push, so the next such break surfaces before the
|
||||
buildds do.
|
||||
|
||||
-- Xavier Roche <xavier@debian.org> Wed, 05 Aug 2026 23:00:24 +0200
|
||||
|
||||
httrack (3.49.17-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release: security fixes in the FTP and HTTP request paths and
|
||||
|
||||
95
debian/copyright
vendored
@@ -44,6 +44,13 @@ License: FSFAP
|
||||
permitted in any medium without royalty provided the copyright notice and
|
||||
this notice are preserved. This file is offered as-is, without any warranty.
|
||||
|
||||
Files: html/fonts/*
|
||||
Copyright: 2020 The League Spartan Project Authors
|
||||
License: OFL-1.1
|
||||
Comment:
|
||||
The woff2 is the latin subset at weight 700, as served by Google Fonts.
|
||||
Upstream declares no Reserved Font Name, so the subset keeps the family name.
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2002-2026 Xavier Roche <xavier@debian.org>
|
||||
License: GPL-3+
|
||||
@@ -106,3 +113,91 @@ License: BSD-3-clause
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
License: OFL-1.1
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
.
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
.
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
.
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
.
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
.
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
.
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
.
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
.
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
.
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
.
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
.
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
.
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
.
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
.
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
.
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
@@ -58,7 +58,9 @@ EXTRA_DIST = README.md run-fuzzers.sh \
|
||||
corpus/singlefile/img-src.html corpus/singlefile/link-rel.html \
|
||||
corpus/singlefile/style-block.html corpus/singlefile/style-attr.html \
|
||||
corpus/singlefile/srcset.html corpus/singlefile/rawtext.html \
|
||||
corpus/singlefile/malformed.html corpus/singlefile/many-attrs.html \
|
||||
corpus/singlefile/malformed.html \
|
||||
corpus/singlefile/mark-at-eof.html corpus/singlefile/mark-only.html \
|
||||
corpus/singlefile/mark-degenerate.html corpus/singlefile/traversal.html \
|
||||
corpus/sitemap/urlset.xml corpus/sitemap/sitemapindex.xml \
|
||||
corpus/sitemap/truncated.xml corpus/sitemap/urlset.xml.gz \
|
||||
corpus/arc/roundtrip.arc corpus/arc/truncated.arc \
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<img src="a.png">
|
||||
<img src=big.png alt=over-cap>
|
||||
<img src="../escape.png"><img src="/abs.png"><img src="data:,x">
|
||||
<img src="a.png">
|
||||
<img src=big.png alt=over-cap>
|
||||
<img src="../escape.png"><img src="/abs.png">
|
||||
<img src="data:,x">
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<link rel="stylesheet" href="s.css">
|
||||
<link rel=icon href=a.png>
|
||||
<link rel="next" href="p2.html">
|
||||
<link rel="preload" href="j.js">
|
||||
<link rel="stylesheet" href="s.css">
|
||||
<link rel="icon" href="a.png">
|
||||
<link rel="canonical" href="other.html">
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
<img src="unterminated.png
|
||||
<div style="background:url(a.png">
|
||||
<style>@import url(
|
||||
<!-- unterminated comment
|
||||
<a href=
|
||||
<p a=1 b=2 c=3 d=4 e=5 f=6 g=7 h=8 i=9 j=10 title="> <img src=a.png>">x</p>
|
||||
<!--><img src="a.png">
|
||||
<img src="a.png" >
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<img src="a.png" a0="v" a1="v" a2="v" a3="v" a4="v" a5="v" a6="v" a7="v" a8="v" a9="v" a10="v" a11="v" a12="v" a13="v" a14="v" a15="v" a16="v" a17="v" a18="v" a19="v" a20="v" a21="v" a22="v" a23="v" a24="v" a25="v" a26="v" a27="v" a28="v" a29="v" a30="v" a31="v" a32="v" a33="v" a34="v" a35="v" a36="v" a37="v" a38="v" a39="v" a40="v" a41="v" a42="v" a43="v" a44="v" a45="v" a46="v" a47="v" a48="v" a49="v" a50="v" a51="v" a52="v" a53="v" a54="v" a55="v" a56="v" a57="v" a58="v" a59="v" a60="v" a61="v" a62="v" a63="v" a64="v" a65="v" a66="v" a67="v" a68="v" a69="v">
|
||||
1
fuzz/corpus/singlefile/mark-at-eof.html
Normal file
@@ -0,0 +1 @@
|
||||
a.png
|
||||
5
fuzz/corpus/singlefile/mark-degenerate.html
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
==
|
||||
""
|
||||
a.png#!htsinlin
|
||||
#!htsinlin
|
||||
1
fuzz/corpus/singlefile/mark-only.html
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<script>var s="</scripting>"; if(a</b) x=1;</script>
|
||||
<script src="j.js"></script>
|
||||
<textarea></textareas></textarea>
|
||||
<title></titles></title>
|
||||
<script src="j.js"></script>
|
||||
<script>var u="a.png";</script>
|
||||
<textarea>a.png</textarea>
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
<img srcset="a.png 1x, big.png 2x, a.png 100w">
|
||||
<source srcset="a.png,, a.png 2x," src="a.png">
|
||||
<img srcset="a.png 1x, big.png 2x, a.png 480w">
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
<div style="background:url(a.png);list-style:url('a.png')"></div>
|
||||
<p style='background:url("a.png")'>x</p>
|
||||
<div style="background:url(a.png)"></div>
|
||||
<div style='background:url("a.png")'></div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<style>@import "s.css";
|
||||
@import url(sub/b.css);
|
||||
div{background:url(a.png)}
|
||||
/* url(a.png) */ p:after{content:"url(a.png)"}
|
||||
<style>@import "s.css";
|
||||
@import url(sub/b.css);
|
||||
div{background:url(a.png)}
|
||||
</style>
|
||||
|
||||
4
fuzz/corpus/singlefile/traversal.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<img src="../../../../etc/passwd">
|
||||
<img src="a.png#frag?q=1">
|
||||
<img src="sub/../a.png">
|
||||
<img src="./a.png">
|
||||
@@ -60,6 +60,10 @@ static void sf_cleanup(void) {
|
||||
(void) remove(sf_root);
|
||||
}
|
||||
|
||||
/* One httrackp for the whole run: the mark secret lives on it, so a fresh one
|
||||
per input would make every mark in the corpus unrecognisable. */
|
||||
static httrackp *sf_opt = NULL;
|
||||
|
||||
/* A missing asset would silently reduce the target to its parser half. */
|
||||
static void sf_write(const char *name, const char *data, size_t len) {
|
||||
char path[700];
|
||||
@@ -76,6 +80,48 @@ static void sf_text(const char *name, const char *data) {
|
||||
sf_write(name, data, strlen(data));
|
||||
}
|
||||
|
||||
/* Append ref plus a real mark for it. The secret is drawn per httrackp, so a
|
||||
fixture cannot spell one; every mark the target sees is built here. */
|
||||
static void sf_marked(String *out, const char *ref, char cls) {
|
||||
char mark[SINGLEFILE_MARK_MAX];
|
||||
|
||||
StringCat(*out, ref);
|
||||
StringCat(*out,
|
||||
singlefile_mark(sf_opt, mark, sizeof(mark), cls, strlen(ref)));
|
||||
}
|
||||
|
||||
/* \001<ref>\002 in an input becomes <ref> plus its mark, which is the only
|
||||
way a corpus file can reach the mark parser at all. */
|
||||
static void sf_expand_input(const char *in, size_t len, String *out) {
|
||||
size_t i, start = 0;
|
||||
|
||||
StringClear(*out);
|
||||
for (i = 0; i < len; i++) {
|
||||
if (in[i] == '\001') {
|
||||
start = StringLength(*out);
|
||||
} else if (in[i] == '\002') {
|
||||
char mark[SINGLEFILE_MARK_MAX];
|
||||
|
||||
StringCat(*out, singlefile_mark(sf_opt, mark, sizeof(mark),
|
||||
SINGLEFILE_CLASS_ANY,
|
||||
StringLength(*out) - start));
|
||||
} else {
|
||||
StringAddchar(*out, in[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sf_css(const char *name, const char *pre, const char *ref,
|
||||
const char *post) {
|
||||
String body = STRING_EMPTY;
|
||||
|
||||
StringCopy(body, pre);
|
||||
sf_marked(&body, ref, SINGLEFILE_CLASS_ANY);
|
||||
StringCat(body, post);
|
||||
sf_write(name, StringBuff(body), StringLength(body));
|
||||
StringFree(body);
|
||||
}
|
||||
|
||||
static void sf_init(void) {
|
||||
static const char png[] = "\x89PNG\r\n\x1a\n";
|
||||
static const char big[4096] = "\x89PNG";
|
||||
@@ -83,6 +129,9 @@ static void sf_init(void) {
|
||||
char path[700];
|
||||
|
||||
hts_init();
|
||||
sf_opt = hts_create_opt();
|
||||
sf_opt->log = sf_opt->errlog = NULL;
|
||||
sf_opt->single_file_max_size = FUZZ_SF_CAP;
|
||||
snprintf(sf_root, sizeof(sf_root), "%s/httrack-fuzz-sf-XXXXXX",
|
||||
tmp != NULL && tmp[0] != '\0' ? tmp : "/tmp");
|
||||
if (mkdtemp(sf_root) == NULL)
|
||||
@@ -95,37 +144,50 @@ static void sf_init(void) {
|
||||
sf_write("a.png", png, sizeof(png) - 1);
|
||||
sf_write("big.png", big, sizeof(big));
|
||||
sf_text("j.js", "var x=1;\n");
|
||||
/* @import plus a url(), so an inlined stylesheet recurses and its own
|
||||
relative reference is rebased. */
|
||||
sf_text("s.css", "@import url(sub/b.css);\ndiv{background:url(a.png)}\n");
|
||||
sf_text("sub/b.css", "p{background:url(../a.png)}\n");
|
||||
/* Marked, so an inlined stylesheet recurses into its own marks and its
|
||||
un-inlinable reference is rebased; unmarked assets leave the target as a
|
||||
bare scan that reaches nothing. */
|
||||
{
|
||||
String css = STRING_EMPTY;
|
||||
|
||||
StringCopy(css, "@import url(");
|
||||
sf_marked(&css, "sub/b.css", SINGLEFILE_CLASS_CSS);
|
||||
StringCat(css, ");\ndiv{background:url(");
|
||||
sf_marked(&css, "a.png", SINGLEFILE_CLASS_ANY);
|
||||
StringCat(css, ")}\np{background:url(");
|
||||
sf_marked(&css, "big.png", SINGLEFILE_CLASS_ANY);
|
||||
StringCat(css, ")}\n");
|
||||
sf_write("s.css", StringBuff(css), StringLength(css));
|
||||
StringFree(css);
|
||||
}
|
||||
sf_css("sub/b.css", "p{background:url(", "../a.png", ")}\n");
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
static int inited = 0;
|
||||
|
||||
String out = STRING_EMPTY;
|
||||
httrackp *opt;
|
||||
/* Exact-length, unterminated: the rewriter is span-based, so ASan bounds a
|
||||
read past html_len instead of it landing on a terminator. */
|
||||
char *html = malloct(size != 0 ? size : 1);
|
||||
String in = STRING_EMPTY;
|
||||
char *html;
|
||||
size_t html_len;
|
||||
|
||||
if (!inited) {
|
||||
sf_init();
|
||||
inited = 1;
|
||||
}
|
||||
memcpy(html, data, size);
|
||||
|
||||
opt = hts_create_opt();
|
||||
opt->log = opt->errlog = NULL;
|
||||
opt->single_file_max_size = FUZZ_SF_CAP;
|
||||
sf_expand_input((const char *) data, size, &in);
|
||||
html_len = StringLength(in);
|
||||
/* Exact-length, unterminated: the rewriter is span-based, so ASan bounds a
|
||||
read past html_len instead of it landing on a terminator. */
|
||||
html = malloct(html_len != 0 ? html_len : 1);
|
||||
memcpy(html, StringBuff(in), html_len);
|
||||
StringFree(in);
|
||||
|
||||
StringClear(out);
|
||||
(void) singlefile_rewrite_html(opt, sf_root, sf_page, html, size,
|
||||
(void) singlefile_rewrite_html(sf_opt, sf_root, sf_page, html, html_len,
|
||||
SINGLEFILE_MAX_PAGE_SIZE, &out);
|
||||
|
||||
StringFree(out);
|
||||
freet(html);
|
||||
hts_free_opt(opt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
40
history.txt
@@ -4,6 +4,46 @@ HTTrack Website Copier release history:
|
||||
|
||||
This file lists all changes and fixes that have been made for HTTrack
|
||||
|
||||
3.49-20
|
||||
+ Fixed: a link to another host whose name looked like a file was scanned as a page, so one link could mirror the whole foreign site on the referring page's depth budget (#121)
|
||||
+ Fixed: a size-bounded filter built both of its filter URLs wrong when the path had no leading slash (#1095)
|
||||
+ Fixed: a mirror told to quit while an FTP file was being received announced the exit and then waited forever on that slot (#1106)
|
||||
+ Fixed: stopping an FTP transfer closed its data socket twice, so a threaded crawl could lose another worker's connection (#1090)
|
||||
+ Fixed: WebHTTrack's welcome page opened its language menu blank instead of marking the language in use (#1084)
|
||||
+ Fixed: two suite tests failed on the hppa, powerpc and ppc64 Debian buildds, holding the package back on those ports (#1108)
|
||||
+ Fixed: a growable string could wrap its capacity to zero instead of saturating (#1062)
|
||||
+ Changed: the macOS disk image carries its architecture in its name, so an Intel user can tell before downloading that the build is for Apple Silicon (#1083)
|
||||
+ Changed: refreshed the GUI guide, its screenshots, the documentation typography and the footer contrast
|
||||
+ Changed: settled on one spelling of the product name across the docs and the site
|
||||
+ Changed: multiple internal hardening, build, test and CI improvements
|
||||
|
||||
3.49-19
|
||||
+ Fixed: an over-long user name in an ftp:// URL was truncated at the credential boundary, so the login went to a different account (#1032)
|
||||
+ Fixed: an over-long FTP path or host name aborted the process instead of failing that one link (#1019)
|
||||
+ Fixed: an FTP crawl ignored --timeout and --max-time, so a server that went quiet held a slot for five minutes (#1039)
|
||||
+ Fixed: an FTP crawl of a dead host took two minutes to give up, and no signal could shorten it (#1059)
|
||||
+ Fixed: the engine released the transfer slots while an FTP thread was still writing to one, crashing a mirror that hit its size or time limit (#1051)
|
||||
+ Fixed: Ctrl-C did not shorten a connection or a name lookup already in flight, so ending a crawl against an unreachable host took minutes (#1073)
|
||||
+ Fixed: a crawl that gave up mid-loop, on the link limit or an abort, lost its WARC archive and its change report, and a WARC written past teardown was stranded in a .tmp file (#1061, #1060)
|
||||
+ Fixed: a crawl that rolled back for want of data still replaced the previous WARC archive, stranding its temporary and never writing its index; a stale or unwritable index is now reported rather than left silently in place (#1053)
|
||||
+ Fixed: a resume the server answered with an unusable Content-Range deleted the partial file and never fetched it again; the restart no longer spends the retry budget, and is latched to one per link (#581, #1052)
|
||||
+ Fixed: a long argument to -n or -O smashed the stack through an unbounded panic message, and the growable arrays could wrap their capacity to zero (#1040)
|
||||
+ Fixed: --single-file could write a reference mark longer than it reads back, leaving it in the delivered page as visible text (#1054, #1069)
|
||||
+ Fixed: on a terminal with no input left, a crawl toggled between the spinner and the full panel on every pass (#1072)
|
||||
+ Fixed: -%v1 ended each line with a carriage return, so the lines overwrote each other and a redirected log was unreadable; -%v2 now paints its panel only on a terminal
|
||||
+ Fixed: the installed socket headers did not compile under -std=c99 without _POSIX_C_SOURCE (#1001)
|
||||
+ Fixed: the 16 px application icon rendered every stem as grey (#938)
|
||||
+ Fixed: the desktop files installed outside the data directory, and the AppStream metainfo declared an icon name that is not a stock one
|
||||
+ Fixed: the build failed on distributions whose coreutils are not GNU's (#1042)
|
||||
+ Changed: --single-file drops its own HTML and CSS scanner and reuses the crawler's parser, so it follows the same references the mirror does (#749)
|
||||
+ Changed: updated Turkish translation, and repaired two mangled Polish strings (#306)
|
||||
+ Changed: multiple internal hardening, build, test and CI improvements
|
||||
|
||||
3.49-18
|
||||
+ Fixed: the 3.49.17 package build failed on four architectures: the test suite's mmap interposer did not compile on armhf, powerpc or hppa, and the alternate-stack test rejected loong64's shorter backtrace (#1023)
|
||||
+ Fixed: the test suite failed on a host with no ps command, such as a Fedora build root; its hang diagnostics now read /proc directly (#1021)
|
||||
+ Changed: multiple internal test and CI improvements, including a cross-compile matrix covering the Debian ports architectures
|
||||
|
||||
3.49-17
|
||||
+ New: a pkg-config file, libhttrack.pc, ships with the development headers (#1018)
|
||||
+ Fixed: a crawled page could read the WebHTTrack session id and drive the control panel; the id is now unguessable and cross-origin commands are refused (#877)
|
||||
|
||||
@@ -4,6 +4,7 @@ HelpHtmldir = $(htmldir)
|
||||
HelpHtmlimgdir = $(HelpHtmldir)/img
|
||||
HelpHtmldivdir = $(HelpHtmldir)/div
|
||||
HelpHtmlimagesdir = $(HelpHtmldir)/images
|
||||
HelpHtmlfontsdir = $(HelpHtmldir)/fonts
|
||||
HelpHtmlTxtdir = $(HelpHtmldir)
|
||||
WebHtmldir = $(HelpHtmldir)/server
|
||||
WebHtmlimagesdir = $(HelpHtmldir)/server/images
|
||||
@@ -15,7 +16,7 @@ WebIcon64x64dir = $(datadir)/icons/hicolor/64x64/apps
|
||||
WebIcon128x128dir = $(datadir)/icons/hicolor/128x128/apps
|
||||
WebIcon256x256dir = $(datadir)/icons/hicolor/256x256/apps
|
||||
WebIconScalabledir = $(datadir)/icons/hicolor/scalable/apps
|
||||
VFolderEntrydir = $(prefix)/share/applications
|
||||
VFolderEntrydir = $(datadir)/applications
|
||||
MetaInfodir = $(datadir)/metainfo
|
||||
|
||||
# Wildcards are globbed against $(srcdir): a bare "*.html" is resolved against
|
||||
@@ -27,6 +28,8 @@ HelpHtml_DATA = $(srcdir)/*.html $(srcdir)/*.js $(srcdir)/*.css
|
||||
HelpHtmldiv_DATA = div/search.sh
|
||||
HelpHtmlimg_DATA = $(srcdir)/img/*
|
||||
HelpHtmlimages_DATA = $(srcdir)/images/*
|
||||
# doc.css reaches the woff2 by a relative URL, so it installs beside the pages.
|
||||
HelpHtmlfonts_DATA = $(srcdir)/fonts/*
|
||||
HelpHtmlTxt_DATA = ../greetings.txt ../history.txt ../license.txt
|
||||
WebHtml_DATA = $(srcdir)/server/*.html $(srcdir)/server/*.js $(srcdir)/server/*.css
|
||||
WebHtmlimages_DATA = $(srcdir)/server/images/*
|
||||
@@ -45,6 +48,7 @@ VFolderEntry_DATA = $(srcdir)/server/div/*.desktop
|
||||
MetaInfo_DATA = $(srcdir)/server/div/*.metainfo.xml
|
||||
|
||||
EXTRA_DIST = $(HelpHtml_DATA) $(HelpHtmlimg_DATA) $(HelpHtmlimages_DATA) \
|
||||
$(HelpHtmlfonts_DATA) \
|
||||
$(HelpHtmldiv_DATA) $(WebHtml_DATA) $(WebHtmlimages_DATA) \
|
||||
$(WebPixmap_DATA) $(WebIcon16x16_DATA) $(WebIcon32x32_DATA) $(WebIcon48x48_DATA) \
|
||||
$(WebIcon64x64_DATA) $(WebIcon128x128_DATA) $(WebIcon256x256_DATA) \
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
@@ -155,6 +155,8 @@ rather than on <tt>url</tt> when a mirror is known to carry legacy-charset URLs.
|
||||
|
||||
<h3 id="example">Example</h3>
|
||||
|
||||
One captured run; <tt>generator</tt> and <tt>date</tt> will read differently in yours.
|
||||
|
||||
<pre>
|
||||
{
|
||||
"schema": 1,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
22
html/doc.css
@@ -32,6 +32,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Additions stay out of the palette block above: it is kept byte-identical with the website's. */
|
||||
:root {
|
||||
--body-font: system-ui, -apple-system, "Segoe UI", Roboto, "Trebuchet MS", Verdana, sans-serif;
|
||||
}
|
||||
|
||||
/* Relative URL: the docs are read from an installed directory too. */
|
||||
@font-face {
|
||||
font-family: "League Spartan";
|
||||
src: url(fonts/league-spartan-700-latin.woff2) format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
/* The plain declaration before each var() is what IE11 gets: it drops the
|
||||
@@ -44,6 +58,7 @@ body {
|
||||
color: #111;
|
||||
color: var(--ink);
|
||||
font: 1em/1.6 "Trebuchet MS", Verdana, system-ui, -apple-system, "Segoe UI", sans-serif;
|
||||
font-family: var(--body-font);
|
||||
}
|
||||
|
||||
/* ---- page frame ---- */
|
||||
@@ -72,7 +87,6 @@ body {
|
||||
/* A one-line label has no use for the body's prose leading. */
|
||||
line-height: 1;
|
||||
padding: .3rem .4rem;
|
||||
margin-top: .4rem;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
@@ -106,10 +120,11 @@ body {
|
||||
.wrap.solo { display: block; }
|
||||
}
|
||||
|
||||
/* Colour inherited: nothing lighter than --ink reaches 4.5:1 on the --field
|
||||
this sits on, and at .8em it is small text. */
|
||||
footer {
|
||||
max-width: 68rem;
|
||||
margin: .5rem auto 0;
|
||||
color: #eef;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
@@ -121,6 +136,9 @@ footer {
|
||||
|
||||
h2, h3 { scroll-margin-top: 1rem; }
|
||||
|
||||
/* Top two levels only: a display face reads worse than the system font over prose. */
|
||||
h1, h2 { font-family: "League Spartan", var(--body-font); font-weight: 700; }
|
||||
|
||||
h1 { font-size: 1.9em; margin: 0 0 .3em; line-height: 1.2; }
|
||||
h2 { font-size: 1.45em; margin: 2.5em 0 .5em; padding-bottom: .2em; border-bottom: 2px solid var(--rule); }
|
||||
h3 { font-size: 1.15em; margin: 2em 0 .4em; }
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
93
html/fonts/OFL.txt
Normal file
@@ -0,0 +1,93 @@
|
||||
Copyright 2020 The League Spartan Project Authors (https://github.com/theleagueof/league-spartan)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
BIN
html/fonts/league-spartan-700-latin.woff2
Normal file
@@ -13,12 +13,14 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- doc-chrome:masthead -->
|
||||
<a class="skip" href="#main">Skip to content</a>
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
<!-- /doc-chrome:masthead -->
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
@@ -58,6 +60,9 @@
|
||||
|
||||
<main id="main">
|
||||
|
||||
<!-- Section ids are link API: the redirect stubs and the Android app's contextual help
|
||||
hardcode them, and an app release outlives its engine pin. -->
|
||||
|
||||
<h1>The HTTrack interface, step by step</h1>
|
||||
|
||||
<p class="lede">HTTrack copies a website to your disk so you can read it offline. The same
|
||||
@@ -88,7 +93,7 @@ itself down once those pings stop.</p>
|
||||
<p>Each option also lists its command-line equivalent, so anything you set here can later be
|
||||
scripted. The <a href="cmdguide.html">command-line guide</a> covers that side.</p>
|
||||
|
||||
<div class="note" data-for="droid">
|
||||
<div class="note" data-for="droid" id="droid-first-launch">
|
||||
<p><b>First launch.</b> Android asks for permission to store mirrors on your device. Without
|
||||
it the app cannot save anything, so tap <b>Allow</b>.</p>
|
||||
<figure>
|
||||
@@ -117,13 +122,13 @@ data-for="droid">Tap <b>Next</b></span> to create a project, or open one you alr
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-start.png" alt="WinHTTrack welcome pane" width="1040" height="744">
|
||||
<img data-for="web" src="img/guide-web-start.png" alt="WebHTTrack welcome page" width="1024" height="388">
|
||||
<img data-for="web" src="img/guide-web-start.png" alt="WebHTTrack welcome page" width="1024" height="387">
|
||||
<img data-for="droid" src="img/guide-droid-start.png" alt="HTTrack for Android welcome screen" width="600" height="1300">
|
||||
<figcaption>The welcome screen.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p class="note" data-for="web">The language dropdown starts blank on purpose: its first entry
|
||||
means "leave the interface as it is". Pick a language only if you want to change it.</p>
|
||||
<p class="note" data-for="web">The dropdown shows the language the interface is already in.
|
||||
Picking another one reloads the page in it.</p>
|
||||
|
||||
<p class="note" data-for="web">On macOS, <code>brew install httrack</code> installs WebHTTrack
|
||||
alongside the command line tool. Open <b>HTTrack.app</b> if you have it, or run
|
||||
@@ -138,7 +143,7 @@ together in the list.</p>
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-project-name.png" alt="WinHTTrack project name, category and base path" width="1040" height="744">
|
||||
<img data-for="web" src="img/guide-web-project-name.png" alt="WebHTTrack project name, category and base path" width="1024" height="346">
|
||||
<img data-for="web" src="img/guide-web-project-name.png" alt="WebHTTrack project name, category and base path" width="1024" height="345">
|
||||
<img data-for="droid" src="img/guide-droid-project-name.png" alt="Android project name, category and base path" width="600" height="1300">
|
||||
<figcaption>Project name, category, and where the files go.</figcaption>
|
||||
</figure>
|
||||
@@ -157,7 +162,7 @@ keep their links to each other.</p>
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-project-setup.png" alt="WinHTTrack action and web addresses" width="1040" height="744">
|
||||
<img data-for="web" src="img/guide-web-project-setup.png" alt="WebHTTrack action and web addresses" width="1024" height="496">
|
||||
<img data-for="web" src="img/guide-web-project-setup.png" alt="WebHTTrack action and web addresses" width="1024" height="495">
|
||||
<img data-for="droid" src="img/guide-droid-project-setup.png" alt="Android web address and action" width="600" height="1300">
|
||||
<figcaption>The addresses to copy, and what to do with them.</figcaption>
|
||||
</figure>
|
||||
@@ -212,7 +217,7 @@ port, you point your browser at it as a proxy and click the link or the submit b
|
||||
usual, and the address the browser asks for is added to the project.</p>
|
||||
|
||||
<figure data-for="web">
|
||||
<img data-for="web" src="img/guide-web-add-url.png" alt="WebHTTrack add-a-URL dialog" width="1024" height="634">
|
||||
<img data-for="web" src="img/guide-web-add-url.png" alt="WebHTTrack add-a-URL dialog" width="1024" height="600">
|
||||
<figcaption>Adding a single address, with an optional login.</figcaption>
|
||||
</figure>
|
||||
|
||||
@@ -241,7 +246,7 @@ mirror straight away.</p>
|
||||
|
||||
<figure data-for="win web">
|
||||
<img data-for="win" src="img/guide-win-ready.png" alt="WinHTTrack connection settings before starting" width="1040" height="744">
|
||||
<img data-for="web" src="img/guide-web-ready.png" alt="WebHTTrack ready to start" width="1024" height="508">
|
||||
<img data-for="web" src="img/guide-web-ready.png" alt="WebHTTrack ready to start" width="1024" height="489">
|
||||
<figcaption>The last screen before the mirror runs.</figcaption>
|
||||
</figure>
|
||||
|
||||
@@ -274,7 +279,7 @@ mirrored pages are rewritten to point at each other, so it browses offline in an
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-finished.png" alt="WinHTTrack mirror complete" width="1040" height="744">
|
||||
<img data-for="web" src="img/guide-web-finished.png" alt="WebHTTrack mirror complete" width="1024" height="487">
|
||||
<img data-for="web" src="img/guide-web-finished.png" alt="WebHTTrack mirror complete" width="1024" height="486">
|
||||
<img data-for="droid" src="img/guide-droid-finished.png" alt="Android mirror complete" width="600" height="1300">
|
||||
<figcaption>Done.</figcaption>
|
||||
</figure>
|
||||
@@ -287,7 +292,7 @@ usual causes.</p>
|
||||
<p data-for="win web">The files sit under the base path you chose, in a folder named after the
|
||||
project. Opening <code>index.html</code> there browses the mirror without HTTrack.</p>
|
||||
|
||||
<p data-for="droid">Mirrors are written to
|
||||
<p data-for="droid" id="droid-storage-location">Mirrors are written to
|
||||
<code>/storage/emulated/0/HTTrack/Websites</code>, in a folder named after the project. That is
|
||||
shared storage, so a file manager or a USB cable can reach it, and opening
|
||||
<code>index.html</code> there browses the mirror without the app.</p>
|
||||
@@ -438,7 +443,7 @@ bottom are the ones that keep you welcome.</p>
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-opt-flow-control.png" alt="WinHTTrack Flow Control tab" width="524" height="448">
|
||||
<img data-for="web" src="img/guide-web-opt-flow-control.png" alt="WebHTTrack Flow Control tab" width="1024" height="910">
|
||||
<img data-for="web" src="img/guide-web-opt-flow-control.png" alt="WebHTTrack Flow Control tab" width="1024" height="862">
|
||||
<img data-for="droid" src="img/guide-droid-opt-flow-control.png" alt="Android Flow Control tab" width="600" height="1300">
|
||||
</figure>
|
||||
|
||||
@@ -481,7 +486,7 @@ bottom are the ones that keep you welcome.</p>
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-opt-links.png" alt="WinHTTrack Links tab" width="524" height="448">
|
||||
<img data-for="web" src="img/guide-web-opt-links.png" alt="WebHTTrack Links tab" width="1024" height="781">
|
||||
<img data-for="web" src="img/guide-web-opt-links.png" alt="WebHTTrack Links tab" width="1024" height="749">
|
||||
<img data-for="droid" src="img/guide-droid-opt-links.png" alt="Android Links tab" width="600" height="1300">
|
||||
</figure>
|
||||
|
||||
@@ -518,7 +523,7 @@ bottom are the ones that keep you welcome.</p>
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-opt-build.png" alt="WinHTTrack Build tab" width="524" height="448">
|
||||
<img data-for="web" src="img/guide-web-opt-build.png" alt="WebHTTrack Build tab" width="1024" height="986">
|
||||
<img data-for="web" src="img/guide-web-opt-build.png" alt="WebHTTrack Build tab" width="1024" height="976">
|
||||
<img data-for="droid" src="img/guide-droid-opt-build.png" alt="Android Build tab" width="600" height="1300">
|
||||
</figure>
|
||||
|
||||
@@ -584,7 +589,7 @@ bottom are the ones that keep you welcome.</p>
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-opt-browser-id.png" alt="WinHTTrack Browser ID tab" width="524" height="448">
|
||||
<img data-for="web" src="img/guide-web-opt-browser-id.png" alt="WebHTTrack Browser ID tab" width="1024" height="706">
|
||||
<img data-for="web" src="img/guide-web-opt-browser-id.png" alt="WebHTTrack Browser ID tab" width="1024" height="654">
|
||||
<img data-for="droid" src="img/guide-droid-opt-browser-id.png" alt="Android Browser ID tab" width="600" height="1300">
|
||||
</figure>
|
||||
|
||||
@@ -624,7 +629,7 @@ bottom are the ones that keep you welcome.</p>
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-opt-spider.png" alt="WinHTTrack Spider tab" width="524" height="448">
|
||||
<img data-for="web" src="img/guide-web-opt-spider.png" alt="WebHTTrack Spider tab" width="1024" height="1557">
|
||||
<img data-for="web" src="img/guide-web-opt-spider.png" alt="WebHTTrack Spider tab" width="1024" height="1541">
|
||||
<img data-for="droid" src="img/guide-droid-opt-spider.png" alt="Android Spider tab" width="600" height="1300">
|
||||
</figure>
|
||||
|
||||
@@ -711,7 +716,7 @@ bottom are the ones that keep you welcome.</p>
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-opt-proxy.png" alt="WinHTTrack Proxy tab" width="524" height="448">
|
||||
<img data-for="web" src="img/guide-web-opt-proxy.png" alt="WebHTTrack Proxy tab" width="1024" height="762">
|
||||
<img data-for="web" src="img/guide-web-opt-proxy.png" alt="WebHTTrack Proxy tab" width="1024" height="760">
|
||||
<img data-for="droid" src="img/guide-droid-opt-proxy.png" alt="Android Proxy tab" width="600" height="1300">
|
||||
</figure>
|
||||
|
||||
@@ -748,7 +753,7 @@ bottom are the ones that keep you welcome.</p>
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-opt-log-index-cache.png" alt="WinHTTrack Log, Index, Cache tab" width="524" height="448">
|
||||
<img data-for="web" src="img/guide-web-opt-log-index-cache.png" alt="WebHTTrack Log, Index, Cache tab" width="1024" height="1278">
|
||||
<img data-for="web" src="img/guide-web-opt-log-index-cache.png" alt="WebHTTrack Log, Index, Cache tab" width="1024" height="1266">
|
||||
<img data-for="droid" src="img/guide-droid-opt-log-index-cache.png" alt="Android Log, Index, Cache tab" width="600" height="1300">
|
||||
</figure>
|
||||
|
||||
@@ -847,7 +852,7 @@ bottom are the ones that keep you welcome.</p>
|
||||
|
||||
<figure>
|
||||
<img data-for="win" src="img/guide-win-opt-experts-only.png" alt="WinHTTrack Experts Only tab" width="524" height="448">
|
||||
<img data-for="web" src="img/guide-web-opt-experts-only.png" alt="WebHTTrack Experts Only tab" width="1024" height="1088">
|
||||
<img data-for="web" src="img/guide-web-opt-experts-only.png" alt="WebHTTrack Experts Only tab" width="1024" height="1085">
|
||||
<img data-for="droid" src="img/guide-droid-opt-experts-only.png" alt="Android Experts Only tab" width="600" height="1300">
|
||||
</figure>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 13 KiB |
@@ -10,12 +10,14 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- doc-chrome:masthead -->
|
||||
<a class="skip" href="#main">Skip to content</a>
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
<!-- /doc-chrome:masthead -->
|
||||
|
||||
<div class="wrap solo">
|
||||
<main id="main">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<header class="masthead">
|
||||
<img src="images/wordmark.svg" width="400" height="36" alt="HTTrack Website Copier">
|
||||
<div class="tagline">Open Source offline browser</div>
|
||||
<div class="tagline">Free software offline browser</div>
|
||||
</header>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||