Debian Package Tracker
Register | Log in
Subscribe

httrack

Copy websites to your computer (Offline browser)

Choose email to subscribe with

general
  • source: httrack (main)
  • version: 3.50.4-1
  • maintainer: Xavier Roche (DMD)
  • arch: all any
  • std-ver: 4.7.4
  • VCS: Git (Browse, QA)
versions [more versions can be listed by madison] [old versions available from snapshot.debian.org]
[pool directory]
  • o-o-stable: 3.49.2-1.1
  • oldstable: 3.49.4-1
  • stable: 3.49.6-1
  • testing: 3.50.3-1
  • unstable: 3.50.4-1
versioned links
  • 3.49.2-1.1: [.dsc, use dget on this link to retrieve source package] [changelog] [copyright] [rules] [control]
  • 3.49.4-1: [.dsc, use dget on this link to retrieve source package] [changelog] [copyright] [rules] [control]
  • 3.49.6-1: [.dsc, use dget on this link to retrieve source package] [changelog] [copyright] [rules] [control]
  • 3.50.3-1: [.dsc, use dget on this link to retrieve source package] [changelog] [copyright] [rules] [control]
  • 3.50.4-1: [.dsc, use dget on this link to retrieve source package] [changelog] [copyright] [rules] [control]
binaries
  • httrack
  • httrack-doc
  • libhttrack-dev
  • libhttrack3
  • proxytrack
  • webhttrack
  • webhttrack-common
action needed
43 new commits since last upload, is it time to release? normal
vcswatch reports that this package seems to have new commits in its VCS but has not yet updated debian/changelog. You should consider updating the Debian changelog and uploading this new version into the archive.

Here are the relevant commit logs:
commit 0b84a75ef2f7bb101e29c2334be1e399f94047a5
Author: Xavier Roche <roche@httrack.com>
Date:   Mon Sep 28 22:14:40 2026 +0200

    Skip the deliberate-crash tests on GNU/Hurd (#1831)
    
    Hurd's ext2fs translator has twice asserted and taken the whole VM down
    right after a test crashed a process on purpose. No test had failed
    either time, so the tier-2 hurd leg went red for the host's reason. The
    eight tests whose point is a deliberate crash now skip there.
    
    The cause is not proven. A probe ran faulting processes against the same
    image for 75 minutes and never reproduced the assertion. This trades
    crash coverage on a tier-3 platform for a leg that finishes.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 61c594c19abf5e4f8567369050fb441057158bfe
Author: Xavier Roche <roche@httrack.com>
Date:   Mon Sep 28 16:39:36 2026 +0200

    Reap a watchdog that outlived the driver that started it (#1828)
    
    A process that outlives the test that started it keeps writing to a log
    the teardown has already unlinked. The space is then held by a file with
    no name, which `du` cannot see at any privilege. Such orphans pinned
    11.6 GB of a 16 GB tmpfs here, and the next `make check` reds on
    unrelated tests.
    
    Two producers need different mechanisms. The watchdog outlives a driver
    whose EXIT trap never ran, so `ci_start_native_watchdog()` now records
    its pid beside the log. That trap and test 172's teardown both reap it.
    The sink's own parent is the test, where no trap survives a SIGKILL. It
    now holds a pipe the test owns, and exits when that closes.
    
    A probe decides whether the interpreter can wait on such a pipe. Where
    it cannot, as under MSYS, the sink is the one master starts.
    
    Each fix carries a leg that SIGKILLs the parent and asserts the log is
    released.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Signed-off-by: Xavier Roche <xroche@users.noreply.github.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 9323cb66979ef3babcb4a9995a75f7d2c3b752fe
Author: Xavier Roche <roche@httrack.com>
Date:   Mon Sep 28 12:03:42 2026 +0200

    End the Hurd run when its VM stops answering (#1829)
    
    A Hurd VM that goes down under the suite used to block the run until the
    step timeout, half an hour later. It then read as a suite failure
    although no test had failed. A watchdog now ends the run once the suite
    has gone quiet and ssh stops answering, and the error says the VM went
    down. The leg still goes red, because the ext2fs translator asserting
    under the suite is Hurd's bug and not ours.
    
    Silence alone must not decide this, because a test may legitimately run
    1200s without printing, so the unanswered ssh probes are what call it.
    Test 524 pins that control. This branch's own hurd leg then wedged for
    real and the watchdog called it after 17 minutes rather than 40.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit e0b4ea90784361b1461a608b6f14367fe18681bb
Author: Xavier Roche <roche@httrack.com>
Date:   Mon Sep 28 08:33:45 2026 +0200

    Keep a savename hook from writing outside the mirror (#1826)
    
    `fil_simplifie()` stripped `../` from the save path before the
    `savename` hook ran, and nothing checked what the hook wrote back. A
    hook returning `<host>/../../ESCAPED/page.html` wrote the page outside
    the mirror, at any depth. With no `-O` the root a name joins to is
    empty, so an absolute name escaped with no `../` at all.
    
    The engine now keeps its own name whenever the hook leaves an absolute
    one, or one carrying a `..`, and logs that at LOG_WARNING. It checks
    every name the hook returns. Its own name has to be relative there, so
    it strips leading slashes again right before the callback. `-N100` on a
    `//` URL path leaves one, and `cleanEndingSpaceOrDot()` puts one back by
    emptying a dots-only component. The check is lexical, so a hook aiming
    at a symlink that already sits inside the mirror still writes wherever
    that symlink points.
    
    Closes #1823
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit e1394df122b4471fbf025d60f31023fef839f5b4
Author: Xavier Roche <roche@httrack.com>
Date:   Mon Sep 28 08:11:47 2026 +0200

    Stop sending a request the sendhead hook refused (#1825)
    
    A `sendhead` callback returning anything but 1 closed the socket and set
    "Header refused by external wrapper". Control then fell through to
    `sendc()` and sent the request anyway. Over HTTPS that reaches
    `SSL_write()` with the `ssl_con` that `deletesoc_r()` had already freed
    and NULLed, because it leaves `r->ssl` set. OpenSSL 3.5.7 returns an
    error rather than faulting, so the dereference is latent and
    version-dependent, not a reproduced crash.
    
    Stopping the send is only half of it, and that half is invisible on its
    own. `back_wait()` marked the slot STATUS_WAIT_HEADERS whichever way the
    send went, so its next pass found the closed socket and replaced the
    reason with "Receive Error". The caller now reads the return value and
    finishes the slot, which is what makes the refusal reach the log. The
    status code and retry count are unchanged.
    
    Closes #1822
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 66ce5765204d0ea1275e9c21604d5c1451ed8dbd
Author: Xavier Roche <roche@httrack.com>
Date:   Mon Sep 28 07:17:29 2026 +0200

    Stop hts_getcategories() returning two fake categories (#1824)
    
    `hts_getcategories(path, 1)` prepended the literals "Test category 1"
    and "Test category 2" to every result. A front end listing mirror
    categories therefore showed two projects that do not exist, WinHTTrack's
    category menu being the visible case.
    
    The two strings never reached the deduplication table the real
    categories use, so a project genuinely named "Test category 1" came back
    twice as well. The new self-test pins both: the exact set a caller sees,
    and that name appearing once.
    
    PR #1820 documented the placeholders as intended behaviour a few commits
    ago. That sentence goes too, or the installed header contradicts the
    fix.
    
    Closes #1821
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 6ffb8f2caf54300bbaf4284da2ff56f0fc369216
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 21:53:22 2026 +0200

    Count received bytes under a lock, so no FTP transfer's bytes go missing (#1812)
    
    Every FTP transfer counts its received bytes on its own worker thread,
    so the plain `+=` they all did on one shared total lost adds. `-M` reads
    that total to decide when to stop, so a lost add lets a crawl run past
    the size the user asked for.
    
    The total now sits in a static behind a lock, and
    `HTS_STAT.HTS_TOTAL_RECV` becomes a copy published beside the other
    fields `engine_stats()` refreshes. It uses a lock rather than a 64-bit
    atomic add, because gcc calls libatomic for that where the target has no
    8-byte compare-and-swap.
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit e9e603ef4ee9c0469e412f39a66e470cd791f07e
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 21:38:51 2026 +0200

    Add a ThreadSanitizer CI leg (#1819)
    
    On x86-64 a missing release/acquire pair behaves exactly like a correct
    one, so nothing in CI could guard the pairs #1808 and #1809 added. This
    adds ThreadSanitizer as a non-required leg over the engine self-tests,
    plus 467 and 503, the FTP thread tests the `01_engine-*` glob misses.
    `tools/tsan-suppressions.txt` names the benign readers and never the
    writer. Suppressing `ftp_worker_release` would be one tidier line, but a
    mutant confirmed it also lets a plain publish pass clean. #1809
    described these races and introduced neither. The leg's blind spot is
    the race with a user-visible effect. An FTP worker bumps
    `HTS_TOTAL_RECV` while `back_maxsize_reached` reads it to decide `-M`,
    and this fixture transfers no bytes, so #1812 stays the fix.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 2edb4ec94af72058d6cf734f1db7fb25f377d028
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 21:38:41 2026 +0200

    Name the buffer's capacity where these four write into it (#1815)
    
    Four places wrote into a fixed buffer without naming its capacity. The
    conditional-request headers in htsback.c are built from an etag and a
    date read back out of the cache. Only a clip two functions away bounds
    them. htsindex.c scanned a keyword with a bare "%s". htsserver.c could
    write 260 bytes into the buffer its own header documents as 258, so
    smallserver_init now takes the destination size.
    
    The one with a reachable effect is the backing table. -c is clamped only
    when --bypass-limits is off. A large -c then overflowed the signed
    maxsoc * 32 + 1024, and the engine asked its allocator for a negative
    count. The keyword width has to be a literal, so a static assertion
    beside the buffer is what keeps the two in step.
    
    ---------
    
    Signed-off-by: Xavier Roche <xroche@gmail.com>
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit bb6fc0d69aa15166440cf878cb23f13263bef3f1
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 19:45:18 2026 +0200

    Document every entity in the installed headers (#1820)
    
    Every function, struct field, enum value, macro and typedef in the
    fourteen headers HTTrack installs now carries a contract comment. Each
    says what a return value means, who frees a pointer, and what size a
    caller buffer needs.
    
    Many comments already there were wrong rather than thin. `check_link`
    and `check_mime` documented 0 as "drop the link", where 0 accepts and 1
    refuses, on the callback surface a front end implements. `strclipbuff`
    and `slprintfbuff` were documented as never aborting, which is the
    property that makes them safe for hostile input. Each aborts on a zero
    size.
    
    One line in `htslib.c` changed for the same reason: `no_high & 1` keeps
    high bytes escaped, where the comment said it decodes them.
    
    The change is comments only. Each file's comment-stripped token stream
    and its preprocessor macro table are unchanged against the merge base,
    in both `HTS_INTERNAL_BYTECODE` arms.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit ae733ca408637c063b4a202565c11bda0c226857
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 16:41:05 2026 +0200

    Bound the copies in the installed example wrappers (#1810)
    
    These wrappers are installed twice over: as shared libraries, and as the
    sources users copy. contentfilter had a reachable bug with no CodeQL
    alert on it. It splits its keyword list into a 128-entry pointer array
    and kept writing past the end. 200 one-byte keywords reach that inside a
    single argv element.
    
    The three cpp/unsafe-strcat alerts are a different matter. Those
    wrappers joined an engine buffer to a second string with strcpy plus
    strcat. That is worth bounding in code people copy, but measuring for
    the runtime probes showed no crawl can overflow it. The engine drops a
    link past HTS_URLMAXSIZE before a wrapper sees it: 926 bytes arrives,
    1000 does not. Both destinations are lien_adrfil's own HTS_URLMAXSIZE *
    2, so the worst join is 1534 bytes into 2048. That measurement also
    caught an over-rejection here. The first version sized both buffers at
    1024 and so refused joins the old code handled.
    
    ---------
    
    Signed-off-by: Xavier Roche <xroche@gmail.com>
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 53a94374e5539bf44b6b325a755508613d40b96a
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 16:40:53 2026 +0200

    Refuse a cached save name that leaves the mirror (#1813)
    
    X-Save is a filename read back out of a cache the process did not write.
    Both readers joined it to the mirror root, so a name that walks out of
    that root reaches other files. ProxyTrack opens that path and sends the
    bytes to its client. It binds whatever address argv[1] names, so an
    archive from an untrusted source becomes an arbitrary file read. The
    engine's own reader reaches a rename with the same value.
    
    Rejecting ".." alone is not enough. With no -O the root is "" and the
    cached name is used verbatim, so an absolute one walks straight through.
    A blanket rejection is wrong too, because an absolute name already under
    the mirror is the pre-3.40 shape the engine's own self-test stores on
    purpose. So a name carrying the root has the remainder checked, and
    anything else has to be relative. ProxyTrack keeps the ".."-only test at
    its top, since it routes absolute names into that pre-3.40 branch by
    design. That branch now checks the suffix it actually joins, rather than
    the whole string it was handed.
    
    ---------
    
    Signed-off-by: Xavier Roche <xroche@gmail.com>
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 3a93fe8be8bc39e0139c58550eb2e3945ab54482
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 16:40:46 2026 +0200

    Quit on the second Ctrl+C without running the atexit chain (#1817)
    
    `sig_term()` called `exit()`, which runs every atexit handler in signal
    context. OpenSSL registers its teardown there, so a second ^C freed
    thousands of objects from inside the handler. A `free()` on that path
    can deadlock on the malloc lock the interrupted thread already holds.
    That would wedge the one escape a user has from a mirror that will not
    stop, so `_exit()` replaces it.
    
    `exit()` was also the only thing flushing the log's closing verdict, so
    that write now flushes itself. The cache is byte-identical either way.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit d097ef22650f747c1a3fa426ca4390e15dd0e7d1
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 14:22:27 2026 +0200

    Pin that a banned host's FTP slot is left to its worker (#1818)
    
    A slot at STATUS_FTP_TRANSFER belongs to its worker thread, which is
    still writing the file. No sweep on the crawl thread may end it.
    back_is_live() says so in its comment, and host_ban() does not use it,
    gating on a raw `status >= 0` that 1000 passes.
    
    Nothing is broken today, because the next condition saves it by
    accident. host_ban() gets a bare host name while an FTP url_adr keeps
    its scheme, so the two never match. Normalizing url_adr, or passing a
    full URL, would close a file under a running worker.
    
    This pins the outcome instead. The http slot beside it must still be
    ended, which is what stops the test passing when host_ban() does nothing
    at all.
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 6be25c12720c78ca2cebc497f76c604e283ecde7
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 08:14:06 2026 +0200

    Answer for every allocation these four functions dereference (#1814)
    
    Four functions built something out of a fresh allocation and used it on
    the next line with no NULL check. The debug resolver behind
    HTTRACK_DEBUG_RESOLVE has six of them, and it also handed a half-copied
    address chain back as success. openFunctionLib and hts_mutexinit have
    one each. CodeQL reached the resolver through
    cpp/suspicious-allocation-size, whose own claim about the sockaddr size
    is wrong. A 28-byte sockaddr_in6 behind a sockaddr pointer is the
    getaddrinfo contract, and the reader bounds itself by ai_addrlen.
    
    hts_mutexinit aborts rather than reporting, because it returns void and
    is exported, so reporting would break the ABI. The test reads the source
    rather than starving a run: RLIMIT_AS cannot reach allocations this
    small, and a probe that tried came back reporting success. The answer
    has to name the variable that was just allocated. A first version did
    not require that, and a nearby test on another variable then hid a
    dropped check.
    
    Signed-off-by: Xavier Roche <xroche@gmail.com>
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 89f0d65d17c74716330c731c82a5faee30153ffb
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 08:13:54 2026 +0200

    Set a file's mode through its open descriptor (#1807)
    
    chmod() looks the name up a second time. In the window between the open
    and the chmod, a local process can swap that name for a symlink. We then
    set the mode on the symlink's target. fchmod() on the descriptor we
    already hold cannot be redirected, and htsbauth.c already uses it.
    
    CodeQL flagged three of these. htscache.c and htssinglefile.c carry the
    same shape without an alert, so they move too. The new test then has to
    allow only the two htsback.c calls that chmod after a rename, with no
    descriptor left.
    
    ---------
    
    Signed-off-by: Xavier Roche <xroche@gmail.com>
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 6d1fc9e0bfb08329475a0601c84d5d35e962fe89
Author: Xavier Roche <roche@httrack.com>
Date:   Sun Sep 27 08:13:49 2026 +0200

    Take printf and the log out of the signal handlers, and restore errno (#1811)
    
    `printf` locks stdout and `hts_log_print` allocates, so a ^C landing
    while the mirror held either lock could wedge the process. Every handler
    now writes with `write()` and puts the interrupted thread's errno back.
    
    The "Exit requested by shell or user" log line still appears. The engine
    writes it the next time its loop runs, instead of the handler writing it
    from inside the signal.
    
    The DNS self-test also swapped the resolver backend while an abandoned
    worker was still reading it, which is the race ThreadSanitizer blamed on
    the engine.
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 9e9d3cac0a257c7d99c0973f4f0868dae3c77558
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 23:58:47 2026 +0200

    Keep the timeout sweep off a slot an FTP worker owns (#1816)
    
    back_is_live() exists so no sweep in back_wait() touches a slot its FTP
    worker owns. The timeout sweep tested a raw `status > 0` instead, so its
    exclusion was an accident.
    
    Nothing changes today. A slot only reaches STATUS_FTP_TRANSFER in
    back_add()'s direct-FTP branch, which returns before any timeout is
    assigned. So the sweep's own `timeout > 0` gate never opened for one.
    
    There is no test because the sweep runs only once a non-FTP slot raises
    gestion_timeout (src/htsback.c:3595), which needs st_backstop's
    live-connect fixture. One edge remains, a corrupt spool pairing status
    1000 with a timeout, where the old code ended the slot and this one
    leaves it live.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 3e3a4c8da3fd7c8a5ce6318ce2905cd714069cc6
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 23:27:16 2026 +0200

    Synchronize the FTP slot handoff between the worker and crawl threads (#1809)
    
    An FTP worker published its finished slot with a plain store, and the
    crawl thread polled it with a plain load. On arm64 that lets the crawl
    thread see the ready status and then read a stale `r.msg`. The store is
    now a release, and the one reader that acts on it takes an acquire load.
    The publish also moves under the worker-list lock, which matters only
    with two engines in one process, because `ftp_workers` is static.
    
    Every other read of that word stays plain, because none of them tells
    1000 from 1001, so ThreadSanitizer still reports them. It also still
    reports `back[i].info`, which the worker writes throughout a transfer
    while the display thread reads it. Fixing either one needs a lock rather
    than a barrier.
    
    Test 503 guards the ordering in the source text, because x86 cannot
    observe it and no CI leg builds ThreadSanitizer.
    
    ---------
    
    Signed-off-by: Xavier Roche <xroche@gmail.com>
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit cb5f9b758870d0b3ab824ecd8e426ff91f38e1e2
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 23:00:29 2026 +0200

    Give every engine header a unique include guard (#1806)
    
    httrack.h reused `HTSTOOLS_DEFH`, htstools.h's own guard, so whichever
    header a file included first emptied the other. htsparse.h had no
    whole-file guard at all. Nothing changes in today's build, because
    htstools.h's declarations sit behind `HTS_INTERNAL_BYTECODE`, which
    neither includer defines. The preprocessed output of the four affected
    files is byte-identical before and after.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

commit 9ed333c15005ef8fe593057d0cc503e00de6dd9e
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 18:27:07 2026 +0200

    Make a thread see all of a lock another thread just built (#1808)
    
    `hts_mutexlock()` publishes the lock it builds on first use with a
    compare-and-swap, but read it back with a plain load. A thread could get
    the pointer and still read stale bytes inside the lock. Both reads are
    acquire loads now, which changes memory ordering only and leaves every
    type and signature alone. That makes `htsthread_init()`'s own
    plain-store guard redundant. Deleting it removes a second race, where
    two engines in one process could overwrite a lock one of them already
    held.
    
    Test 501 races eight threads for 64 unbuilt locks. That half cannot fail
    on x86, which never reorders two loads, and a relaxed-ordering mutant
    still prints OK. So the test's source guard is what catches an ordering
    regression in CI, because no leg runs ThreadSanitizer. A local TSan
    build does see it, and on arm64 it is real.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 9e449f5a862a4690c1396be526d1a5ed37803dcf
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 12:55:32 2026 +0200

    Check that a forged cache header line replaces the whole line (#1805)
    
    `corrupt_patch` matched its placeholder as a prefix of the header line,
    and never checked the forged replacement's own length. A placeholder
    longer than the replacement left its tail on the forged value. A
    replacement shorter than `patlen` made memcpy read past the literal and
    splice those bytes into the zip. Either way `-#test=cache-corrupt` gave
    the same verdict whichever length the fixture used. Both lengths and
    both edges of the line are now asserted.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

commit d71e98faca4c9df221370c18e1682f1741d8fe9d
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 12:06:18 2026 +0200

    Fail our own CI build on a compiler warning (#1804)
    
    `--enable-werror` appends `-Werror` to `DEFAULT_CFLAGS`, and the four
    pinned Ubuntu build legs pass it, so a new compiler warning reds a PR.
    
    It defaults to off, so no distribution build and no other CI job
    changes. Turning it on found three real clang warnings, two of them
    fixed here. The third was coucal's own missing format attribute, so it
    went upstream as xroche/coucal#47 and this bumps the pin.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 7e4491b89f960a50b04b0c2b2e5aca0b6c13b6ef
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 10:34:27 2026 +0200

    Add one switch-fallthrough marker gcc and clang both accept (#1802)
    
    `HTS_FALLTHROUGH` expands to the `fallthrough` attribute, and
    `-Wimplicit-fallthrough=5` stops gcc from taking a comment as the
    marker, which clang never accepted. The engine has no unmarked
    fallthrough, so the macro has no caller yet. Test 499 compiles one
    switch per marker form against the build flags it reads out of
    `src/Makefile`.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 61f0566fef29170cfe6effd3abc3b7671e2839a7
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 10:12:29 2026 +0200

    Say why ProxyTrack builds plaintext http:// strings (#1803)
    
    The four `cpp/non-https-url` alerts on `proxytrack.c` are dismissed as
    false positives, and the comment records why. The `http://` prefix
    completes an archive lookup key rather than a fetch target, and
    `proxytrack` imports neither `connect` nor any `SSL_` symbol.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit bd926ac5eef2c651baf9728b25d7a7d5453ab9d1
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 01:34:22 2026 +0200

    Check unsigned wrap in the fuzz build (#1801)
    
    `-fsanitize=undefined` leaves `unsigned-integer-overflow` out, because
    the wrap is defined behaviour. It is also how a bounds test written as
    `controlled + untrusted < limit` passes when it should fail, which is
    the form AGENTS.md bans. The fuzz leg already replays hostile input
    through the parsers under clang, so the check goes there and costs no
    new job.
    
    Two hashes wrap on purpose. MD5 and MurmurHash3 are third-party and
    coucal is a submodule, so they go in an ignorelist. Each path is listed
    twice, because make names a source relatively in-tree and absolutely out
    of tree. The entity table's FNV is ours, so it says so at its own
    definition.
    
    The one remaining `lastI + 2` now tests `lastI` against its unset value.
    That changes no output, which is why only this check sees it.
    
    The control: put that guard back to its wrapping form and
    `fuzz-htsparse` aborts, in-tree and out. With it in place all 14
    harnesses replay clean both ways.
    
    Closes #1796
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 9dfea22d81ae07aee7596ce56ec4e78cfbe9df96
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 00:55:26 2026 +0200

    Turn on seven compiler warnings this code wants (#1798)
    
    Seven warnings this code wants were not on. A full build of master with
    gcc 14 is silent on every one of them, so each is a ratchet rather than
    a cleanup. The two that were not silent are what #1789 and #1793 already
    fixed.
    
    `-Wvla` and `-Walloca` are the ones that matter most here. They refuse a
    stack allocation sized by something read off the wire, and the tree uses
    neither construct, so nothing can start.
    
    Clang keeps four of the seven and the `AX_CHECK_COMPILE_FLAG` probes
    drop the rest, so a clang build gains no new output. `-Wshadow`,
    `-Wnull-dereference`, `-Wlogical-op` and `-Warray-bounds=2` were
    measured too, at 97, 22, 16 and 2 warnings, and stay out.
    
    Closes #1797
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit a4f99cfbeed26e9261a110a483ffa53324fd6bb8
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 00:46:14 2026 +0200

    Zero an uninitialized stack variable, and bound a trailing char[1] (#1800)
    
    `-ftrivial-auto-var-init=zero` zeroes a stack variable that has no
    initializer, so a read before the first write returns 0. MemorySanitizer
    finds those reads in CI and nothing mitigates them in a shipped build.
    `-fstrict-flex-arrays=3` tells `_FORTIFY_SOURCE` that only a `[]` member
    is a flexible array, so a trailing `char x[1]` is bounded as written.
    
    The trap a reviewer would want checked is the first flag reaching the
    MemorySanitizer build, where it would hide exactly what that job looks
    for. It sits under the same `*-fsanitize=*` guard the fortification
    above it already uses, and a `CFLAGS=-fsanitize=memory` configure run
    confirms it is dropped.
    
    Measured with gcc 14: text grows 1.4% and the suite is green. Three
    interleaved rounds of the htsparse fuzz corpus put the runtime
    difference inside the run-to-run spread. Neither flag adds a warning on
    gcc or clang.
    
    Closes #1799
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit da33402bd1cab82d6e4ee44eac7030089c0d50f8
Author: Xavier Roche <roche@httrack.com>
Date:   Sat Sep 26 00:45:17 2026 +0200

    Open the query on a '?' in the first byte of a URL (#1792)
    
    `hts_unescapeUrlSpecial` keeps the offset of the last `%` in `lastI`,
    which starts at `(size_t) -1`, so `lastI + 1` wrapped to 0. At `i == 0`
    the branch that records a `?` was skipped, so `?a+b` unescaped to `?a+b`
    where `x?a+b` gave `x?a b`. A relative link such as `<a href="?q=a+b">`
    is the common way to reach it.
    
    A leading `?` now behaves exactly as a `?` one byte in always did. Over
    999 million pairs, the new output for `?t` equals the old output for
    `x?t` without its leading `x`. Opening the query also cancels a pending
    UTF-8 sequence at a `+`, so an output can change by more than one byte.
    
    Closes #1791
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit b38ed9c3adf7e0eb7bfbb9642faf7435da03b844
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 23:58:07 2026 +0200

    Make ProxyTrack build clean under -Wsign-compare (#1795)
    
    Seven comparisons tested a signed value against a `size_t` or an
    `unsigned long`. Four are `send()` and `sendto()` results. The wrap
    already took the error branch the code wants, so the cast writes down
    what the compiler was doing.
    
    `store.c`'s `fread` site also loses an `(int)` cast on the way into a
    `size_t`. `fetchSize` is bounded by an `int` a few lines above, so the
    truncation was never reachable. Dropping the cast is what lets the
    comparison be typed.
    
    The cast at `proxytrack.c:1291` goes on the `send()` result, not on
    `element->size`. That size comes from the cache archive. One whose low
    32 bits are all ones would compare equal to a `-1` error, reading a
    failed send as a complete one.
    
    Closes #1793
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit cb09f0afedbd36d9856c3a1b89d70a0beea9a3d0
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 23:51:45 2026 +0200

    Drop the unreachable raw IPv6 form from SOCaddr_copyaddr (#1790)
    
    `SOCaddr_copyaddr` tested `data_size == sizeof(struct sockaddr_in)`
    before `data_size == 16` for a raw IPv6 address, and those are the same
    number on every target, so the IPv6 branch was dead. No caller reached
    it, because every raw-length caller sits under `#if HTS_INET6==0` where
    the length is always 4. The doc comment offered the form all the same.
    
    The new `socaddr` self-test pins the forms that do work. It fails when
    the two branches are reordered, the shape that would break a live
    caller, and `-Wduplicated-cond` catches the dead branch coming back.
    
    Closes #1789
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 25650ea5e3bbef248c203b1dc5a4de475b03e0b3
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 23:36:41 2026 +0200

    Make the engine build clean under -Wsign-compare (#1794)
    
    Fourteen comparisons tested a signed value against a `size_t` or an
    unsigned enum, so the signed side converted to unsigned. A guard
    excludes a negative value at every one of them today, but the conversion
    is what would hide the next one.
    
    The object code is unchanged in `htscache`, `htsparse` and `punycode`,
    and in every `htslib` function but `hts_log_vprint`. The other three
    move a comparison from unsigned to signed or widen a loop index, so the
    instructions change and the result does not. `hts_log_vprint` casts
    `opt->debug` to int rather than retyping `level`, because an enum-typed
    `level` reds `-Wswitch` on the switch below it.
    
    The seven sites in `src/proxy/` follow separately.
    
    Part of #1793
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 46c0181357d09965f5157f5b1b0604071876634a
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 21:50:48 2026 +0200

    Say wontfix in the two Hurd skips, rather than promise a fix (#1788)
    
    #1784 and #1785 are closed as wontfix, so the skip in `471` should not
    still carry a `TODO` saying to drop it once #1784 is fixed. A TODO
    nobody can discharge is worse than none.
    
    Each skip now names why it is permanent. `471` because every binary we
    ship sets its own SIGPIPE handler, so nothing we distribute is exposed
    to that defect. `36` because nothing pinned the missing files on the
    engine rather than on a one-processor VM.
    
    Comments only, and both tests still run on every other platform.
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 826fe49e989c271907702887e7ee5784c3f5da32
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 20:37:16 2026 +0200

    Build the cache-corruption fixture once instead of three times (#1787)
    
    `corrupt_build`, `corrupt_build_longetag` and `corrupt_build_etag` were
    the same seventeen lines three times over. They differed only in the
    Etag stored on the victim entry, so the Etag is now an argument and the
    six call sites pass it.
    
    That Etag's byte length is what the forged, same-length header line
    overwriting it must match. The pairing is now visible at the call site
    instead of three hundred lines away.
    
    Two mutants, because a passing test after a fixture refactor proves
    little. Ignoring the new argument kills `-#test=cache-corrupt`. Swapping
    the 20-byte Etag for the 100-byte one does not kill it. It does not on
    master either, so that insensitivity belongs to the test and predates
    this change.
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit ee86c3756636f8521c4f0fc087e6748f46a6336d
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 20:05:41 2026 +0200

    Split the engine self-tests into one file per module (#1786)
    
    Every engine self-test lived in one 17,412-line `htsselftest.c`. That
    file was the most-edited in `src/`: 232 commits in 90 days, against 119
    for the runner-up. 151 of those commits appended a row to the same
    registry array, so concurrent branches collided there.
    
    Each module now carries its own `hts<module>_selftest.c` publishing a
    `selftests_<module>[]` table. The tables are declared in a shared
    prelude, `htsselftest_int.h`, and walked by `hts_selftest()`. Adding a
    test now means one file instead of three.
    
    The tests moved unchanged, so review the proof rather than the 17k
    lines:
    
    - the chunker that partitioned the file round-trips byte-for-byte
    - a check confirms all 405 moved chunks and all 184 registry rows sit in
    their target file
    - `-#test` lists the same 184 names, with the same usage and description
    strings
    - `make check` matches the pre-split baseline at 519 total, 504 pass, 15
    skip
    
    New code is limited to the prelude, `htsselftest_util.c` for the
    fixtures more than one module needed, and the dispatcher walking a list
    of tables. `git clang-format` touched only those lines.
    
    `htsparse.h`, `htsmodules.h`, `htsarrays.h`, `htscodec.h`, `htsproxy.h`
    and `htszlib.h` carry no include guard. That is why the three older
    `*_selftest.c` files now take their includes from the prelude rather
    than keeping their own lists. Adding the guards is left for a separate
    change.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit cde0be49e582aecd94e1c1a53ca97671a153ac1e
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 18:20:31 2026 +0200

    Run the test suite on GNU/Hurd in a qemu VM (#1779)
    
    Four package builds broke on the hurd buildds and every one failed a
    test rather than the compile (#1668, #1717, #1719, #1775). `cross-arch`
    stops at compile, so it sees none of that class. The Debian buildd was
    the first machine to run the suite on a Hurd each time, which is after
    the upload.
    
    `tools/hurd-vm.sh` fetches Debian's prebuilt hurd-amd64 image, grows the
    root filesystem and drops an ssh key into it. It then boots the image
    under KVM and runs the suite. The job sits in `tier2.yml`, and also on
    any pull request touching the driver, so this one runs it.
    
    The image is pinned by date and checked against the archive's own
    SHA512. A boot that never reaches ssh uploads a qemu screendump, because
    the image uses the VGA console and the serial log comes back empty.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 91973e5eb4ba5fb1393cc76077f9c41c8e0fd8f5
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 15:15:59 2026 +0200

    Cover the library's socket writes against SIGPIPE, not just the OpenSSL ones (#1783)
    
    The engine names three mechanisms that stop a broken pipe from killing
    whoever embedded it (#1689), but the plain `send()` path carried only
    one. GNU/Hurd defines `MSG_NOSIGNAL` and ignores it, so nothing covered
    the write there and httrack killed its own process. The library's six
    raw sends now hold the mask.
    
    The proof is on Linux rather than on trust. With `HTS_MSG_NOSIGNAL`
    forced to 0, `471_engine-sigpipe` passes with this change and fails
    without it. The failure reports the same "the engine died on SIGPIPE"
    the Hurd run did.
    
    Review caught a bug the first version introduced. `sigpipe_release()`
    runs `sigtimedwait()`, which reports `EAGAIN` when nothing is pending,
    and two writers in `htsproxy.c` read `errno` on the next statement.
    Every fatal error would have read as a would-block. The wrapper saves
    `errno` now, and the self-test pins it.
    
    Two tests were asserting something the host supplies rather than
    something httrack does. `89` needs `RLIMIT_FSIZE` to stop a write, and
    now measures whether it does. `130` needs the host to tell an RST from a
    clean end of file, which pfinet does not.
    
    `htsserver` and `proxytrack` still send raw. They are separate binaries
    rather than the embedded library. `htslib.h`'s helper does not reach
    those two translation units, so they are left for their own change.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 59fc059e253aee9b2a69aab024990da228a03fa8
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 15:12:37 2026 +0200

    Arm the DNS resolve deadline on a clock NTP cannot step (#1782)
    
    The bounded resolve armed its deadline on the wall clock. A backward NTP
    step therefore extended the resolve by the size of the step, and
    `--timeout` stopped firing for that long. That is the #606 wedge the
    deadline exists to prevent. chrony steps rather than slews past its
    `makestep` threshold, one second on a default install, and a step at
    boot can be far larger.
    
    `mtime_monotonic()` is the DNS self-test's own clock, promoted to the
    engine and now shared with it. The rate limiter's window gets it too.
    The DNS cache does not, because `t_dnscache.stored` is compared against
    a wall-clock age and a backward step has to expire those stamps.
    
    A test may not step the host's clock, so `01_engine-dnstimeout` reads
    the source the way 133 does for gmtime. A deadline armed on one clock
    and compared on the other is caught at runtime by the existing
    self-test.
    
    Closes #1769
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit d3a62fcd5fe5eb6020352dd65c48f86ed0ee34f3
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 15:12:34 2026 +0200

    Read a CSS ident the way CSS does before taking url() (#1781)
    
    The CSS scanner ended a name on anything but an ASCII letter, a digit or
    `_`. So it read `image-url(x)` as a `url()`, fetched `x` and rewrote the
    declaration. CSS Syntax 3 makes `-` an ident code point, so a browser
    reads `image-url(` as one function-token and never resolves that
    argument. Compass and the Rails asset pipeline both define
    `image-url()`, `font-url()` and `asset-url()`. U+1680 and U+FEFF fail
    the same way from the other side. JavaScript reads them as spaces, while
    CSS puts them inside its non-ASCII ident ranges.
    
    Only CSS gets the wider test. JavaScript subtracts across `-`, so
    `image-url("x")` there really is a call to `url()` and stays a link.
    
    Closes #1754
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 282520a08c875b0d94281d540d04da5dd40be7da
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 13:58:22 2026 +0200

    Open an issue when a scheduled canary fails (#1780)
    
    Ten workflows run on a cron and only one of them says anything when it
    fails. `termux-build` went red on 2026-09-24 and the fedora spec canary
    twice the week before, and no issue was opened for any of them.
    
    This watches scheduled runs through `workflow_run` and keeps one issue
    per workflow, labelled `ci-canary`. A red opens it or comments on it,
    and the next green closes it. Only scheduled runs report, because a
    dispatch has somebody reading it and a pull-request run already reports
    on the pull request.
    
    `workflow_run` only fires for workflows on the default branch, so this
    starts working when it merges, not on this PR. `Tier-2` is on the watch
    list ahead of #1778, and naming a workflow that does not exist yet is
    inert.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit e084565b98876731d278d81b553fa375617a89d6
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 13:28:52 2026 +0200

    Move the slow CI legs into a Tier-2 workflow (#1778)
    
    Six configure-variant and packaging jobs leave the pull-request path for
    a new `tier2.yml`. Tier-2 also absorbs the emulated s390x suite and the
    five distro packaging canaries. Measured on this branch, CI goes from 29
    jobs to 23 and from 171 job-minutes to 123.
    
    No required status context moved, so no open PR loses a check.
    `496_ci-tier2-split.test` pins the required list and reds if one ever
    does. It also reds when a workflow absorbed into tier-2 stops being
    called, because one with neither a schedule nor a caller never runs
    again.
    
    What that buys is fewer occupied runner slots, not a shorter pull
    request. A PR still waits about 30 minutes on `libhttrack (x64,
    Release)`, which this does not touch. Run tier-2 against a release
    branch with `gh workflow run tier2.yml --ref <branch>`. The weekly run
    takes master.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 52381d34ec833d162881f65cfcf580b9cc97df7d
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 10:04:08 2026 +0200

    Clip an over-limit --max-retry-after instead of killing the crawl (#1777)
    
    `back_set_retry_after()` clips a server's oversized `Retry-After` and
    logs a notice. `case 'J'` did the opposite with the user's own value,
    and panicked above `HTS_MAX_RETRY_AFTER_LIMIT`, so the crawl never
    started. WebHTTrack's Max Retry-After box carries no bound, so typing
    5000 there cost the whole crawl rather than the option.
    
    An over-limit value is clipped with a notice now. A malformed or
    negative one is still refused.
    
    That upper bound was also an accidental overflow guard. `sscanf("%d")`
    wrapped 99999999999999 to 276447231, which the bound then caught.
    `strtoll` and `ERANGE` take over, so a digit string too wide even for
    `LLint` is refused as malformed.
    
    Test 01 pinned the old behaviour, so 3601 and 99999 move from its
    refused table to a clipped one. That inversion is the review point,
    because #1755 chose refusal deliberately and this reverses it.
    
    Closes #1776
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

commit 6b74afcb475610e8023cc9c3f31da2ad48164b14
Author: Xavier Roche <roche@httrack.com>
Date:   Fri Sep 25 05:34:06 2026 +0200

    Fix the SIGPIPE self-test on GNU/Hurd (#1775)
    
    `3.50.4-1` failed to build on both hurd buildds, because the SIGPIPE
    self-test waits for the peer to answer a write and pfinet never answers.
    The self-test now ends its own write side instead, which gives EPIPE
    whatever the peer does. The arm still catches a regression, because with
    a FIN-only peer on Linux, dropping `HTS_MSG_NOSIGNAL` from `sendc` kills
    the process with SIGPIPE.
    
    ---------
    
    Signed-off-by: Xavier Roche <roche@httrack.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Created: 2026-09-26 Last update: 2026-09-28 23:00
testing migrations
  • This package will soon be part of the auto-openssl transition. You might want to ensure that your package is ready for it. You can probably find supplementary information in the debian-release archives or in the corresponding release.debian.org bug.
  • excuses:
    • Migration status for httrack (3.50.3-1 to 3.50.4-1): Waiting for test results or another package, or too young (no action required now - check later)
    • Issues preventing migration:
    • ∙ ∙ Lintian check waiting for test results on riscv64 - info
    • ∙ ∙ Too young, only 4 of 5 days old
    • Additional info (not blocking):
    • ∙ ∙ Piuparts tested OK - https://piuparts.debian.org/sid/source/h/httrack.html
    • ∙ ∙ Reproduced on amd64 - info
    • ∙ ∙ Reproduced on arm64 - info
    • ∙ ∙ Reproduced on armhf - info
    • ∙ ∙ Reproduced on i386 - info
    • Not considered
news
[rss feed]
  • [2026-09-24] Accepted httrack 3.50.4-1 (source) into unstable (Xavier Roche)
  • [2026-09-23] httrack 3.50.3-1 MIGRATED to testing (Debian testing watch)
  • [2026-09-18] Accepted httrack 3.50.3-1 (source) into unstable (Xavier Roche)
  • [2026-09-16] httrack 3.50.2-1 MIGRATED to testing (Debian testing watch)
  • [2026-09-11] Accepted httrack 3.50.2-1 (source) into unstable (Xavier Roche)
  • [2026-09-08] httrack 3.50.1-1 MIGRATED to testing (Debian testing watch)
  • [2026-09-02] Accepted httrack 3.50.1-1 (source) into unstable (Xavier Roche)
  • [2026-09-01] Accepted httrack 3.50.0-2 (source) into unstable (Xavier Roche)
  • [2026-09-01] Accepted httrack 3.50.0-1 (source) into unstable (Xavier Roche)
  • [2026-08-28] Accepted httrack 3.49.25-1 (source) into unstable (Xavier Roche)
  • [2026-08-26] Accepted httrack 3.49.24-1 (source) into unstable (Xavier Roche)
  • [2026-08-26] httrack 3.49.23-1 MIGRATED to testing (Debian testing watch)
  • [2026-08-21] Accepted httrack 3.49.23-1 (source) into unstable (Xavier Roche)
  • [2026-08-21] httrack 3.49.22-1 MIGRATED to testing (Debian testing watch)
  • [2026-08-16] Accepted httrack 3.49.22-1 (source) into unstable (Xavier Roche)
  • [2026-08-13] Accepted httrack 3.49.21-2 (source) into unstable (Xavier Roche)
  • [2026-08-12] Accepted httrack 3.49.21-1 (source) into unstable (Xavier Roche)
  • [2026-08-10] Accepted httrack 3.49.20-1 (source) into unstable (Xavier Roche)
  • [2026-08-08] Accepted httrack 3.49.19-1 (source) into unstable (Xavier Roche)
  • [2026-08-05] Accepted httrack 3.49.18-1 (source) into unstable (Xavier Roche)
  • [2026-08-05] Accepted httrack 3.49.17-1 (source) into unstable (Xavier Roche)
  • [2026-08-04] Accepted httrack 3.49.16-1 (source) into unstable (Xavier Roche)
  • [2026-07-30] Accepted httrack 3.49.15-1 (source) into unstable (Xavier Roche)
  • [2026-07-29] httrack 3.49.14-1 MIGRATED to testing (Debian testing watch)
  • [2026-07-24] Accepted httrack 3.49.14-1 (source) into unstable (Xavier Roche)
  • [2026-07-23] httrack 3.49.13-1 MIGRATED to testing (Debian testing watch)
  • [2026-07-18] Accepted httrack 3.49.13-1 (source) into unstable (Xavier Roche)
  • [2026-07-16] httrack 3.49.12-1 MIGRATED to testing (Debian testing watch)
  • [2026-07-10] Accepted httrack 3.49.12-1 (source) into unstable (Xavier Roche)
  • [2026-07-10] httrack 3.49.11-1 MIGRATED to testing (Debian testing watch)
  • 1
  • 2
bugs [bug history graph]
  • all: 0
links
  • homepage
  • lintian
  • buildd: logs, reproducibility, cross
  • popcon
  • browse source code
  • other distros
  • security tracker
  • screenshots
ubuntu Ubuntu logo [Information about Ubuntu for Debian Developers]
  • version: 3.50.0-2

Debian Package Tracker — Copyright 2013-2025 The Distro Tracker Developers
Report problems to the tracker.debian.org pseudo-package in the Debian BTS.
Documentation — Bugs — Git Repository — Contributing