Skip to content

Latest commit

 

History

112 Commits

Folders and files

Repository files navigation

MacHTTrack

Ícone do MacHTTrack

Interface gráfica nativa de macOS para o HTTrack Website Copier.

O HTTrack copia sites inteiros para o disco, mas no macOS só existe como linha de comando — o WebHTTrack do mundo Unix serve um wizard HTML num mini-servidor e depende do navegador. O MacHTTrack é um app Mac de verdade: SwiftUI, uma janela, sidebar de sites, progresso ao vivo.

Completa a família do projeto: WinHTTrack no Windows, WebHTTrack no Unix, MacHTTrack no macOS.

Status: versão 1.0 — baixe o .app. Adicione uma URL, escolha a pasta, acompanhe o progresso ao vivo, pare e retome. O httrack-agent espelha pela linha de comando e reporta progresso em JSON Lines; toda a lógica mora no app SwiftUI. Detalhes de arquitetura no design doc.

Captura de tela

O MacHTTrack espelhando um site: sidebar de sites à esquerda, progresso ao vivo e log à direita

O que faz

  • Espelhar sites — URL, pasta de destino, profundidade e limite de velocidade
  • Configurar por site, em abas no estilo WinHTTrack — regras de incluir/excluir (-*.zip, +*.pdf), robots.txt, user-agent e referer
  • Rede e autenticação — proxy (com usuário e senha) e login HTTP do site, guardados no Keychain, nunca no sites.json
  • Acompanhar e controlar — progresso ao vivo, conexões ativas e log; parar e retomar de onde parou
  • Gerir a lista — nome amigável para cada site e excluir, opcionalmente apagando a pasta do espelho

Um download por vez, por ora. No radar: vários espelhos simultâneos e mais gestão das cópias (tamanho em disco, revelar no Finder, abrir no navegador).

Fora do escopo: busca dentro do conteúdo baixado, distribuição pública (assinatura Developer ID, notarização, App Store), Windows e Linux.

Como funciona

Um único .app, sem instalador e sem dependência externa. Dentro dele, dois executáveis:

MacHTTrack.app/Contents/MacOS/
├── MacHTTrack        ← app SwiftUI
└── httrack-agent     ← motor: libhttrack.a + OpenSSL, tudo estático

O app lança um httrack-agent por download. As opções do mirror vão por argv, na mesma sintaxe da CLI do HTTrack; só os segredos vão por stdin, como linhas CHAVE=valor, para não ficarem visíveis no ps. O progresso volta por stdout em JSON Lines, alimentado pelos callbacks loop e filesave da libhttrack.

Rodando o agente na mão

O agente é exercitável inteiramente pelo terminal — é assim por design. O stdin precisa ser fechado: os segredos são lidos até EOF, antes da primeira linha de saída, então sem redirecionamento o processo fica parado esperando, sem emitir nada (o agente avisa no stderr quando percebe que o stdin é um terminal).

# Sem segredo nenhum — repare no </dev/null.
agent/httrack-agent "http://example.com/" -O /tmp/espelho -r2 --quiet </dev/null

# Com credencial HTTP: pelo stdin, nunca no argv (o `ps` mostra argv).
printf 'HTTP_USER=alice\nHTTP_PASSWORD=hunter2\n' \
  | agent/httrack-agent "http://example.com/privado/" -O /tmp/espelho -r2 --quiet

# Atrás de um proxy que exige autenticação.
printf 'PROXY_USER=bob\nPROXY_PASSWORD=s3cr3t\n' \
  | agent/httrack-agent "http://example.com/" -P "http://proxy.local:3128" \
      -O /tmp/espelho -r2 --quiet

Chaves aceitas no stdin: HTTP_USER, HTTP_PASSWORD, PROXY_USER, PROXY_PASSWORD — desconhecidas são ignoradas de propósito, para o app poder acrescentar novas sem quebrar um agente antigo. A credencial HTTP é registrada para o host da URL semente; ela precisa, portanto, trazer esquema (http:/https:, com o // opcional).

O agente recusa a execução (código 2, um error de nível fatal no protocolo, hts_main2() nunca roda) quando não consegue decidir com segurança de quem são os bytes da autoridade de uma URL semente — tipicamente uma credencial com /, ?, # ou @ não codificado. A mensagem diz qual codificação usar (%2F, %3F, %23, %40). Vale inclusive para uma URL credenciada com @ no caminho ou na query (http://user:pass@host/p?x=a@b → escreva x=a%40b). O raciocínio inteiro, ramo por ramo, está em report_strip_argv_credentials() (agent/agent_report.c).

Cada linha da saída é um JSON: ready primeiro, done por último, progress/file/error no meio — com a exceção das falhas de arranque, documentadas em "Protocolo do agente" no design doc.

Por que processos separados? A API do HTTrack é process-global em vários pontos — httrack-library.h:191-192 avisa que hts_get_stats() devolve um static "not thread-safe and overwritten by the next call". Dois mirrors no mesmo processo corrompem estado. Um processo por mirror resolve isso por construção, isola falhas do C e mantém a UI responsiva.

Requisitos

  • macOS 26 ou superior, Apple Silicon
  • Xcode 26+
  • Homebrew com openssl@3 (só para construir; o .app resultante não depende do Homebrew)
  • autoconf, automake, libtool (para construir a libhttrack)

Build

git submodule update --init --recursive
./scripts/build-libhttrack.sh     # libhttrack.a estática
make -C agent                     # httrack-agent
make -C agent check               # suíte do agente (5 conjuntos)
swift test                        # suíte do app
./scripts/assemble-app.sh         # monta build/MacHTTrack.app
open build/MacHTTrack.app

O make roda scripts/check-linkage.sh automaticamente — se o agente ganhar qualquer dependência fora de /usr/lib, o build falha.

O make -C agent check roda a suíte inteira do agente: os dois testes unitários (test-json, test-secrets) e as três suítes de shell (tests/integration.sh, tests/test_stop.sh, tests/test_tls.sh). As de shell sobem servidores HTTP/HTTPS locais com python3 e levam alguns minutos.

A dependência C é construída estaticamente e embutida no binário. O ponto crítico, que o scripts/build-libhttrack.sh e o agent/Makefile já resolvem: os .a do OpenSSL devem ser passados por caminho absoluto. O flag --disable-shared governa a libhttrack, não o OpenSSL — com -lssl -lcrypto o linker acha .dylib e .a no mesmo diretório e prefere a dinâmica, prendendo o binário a /opt/homebrew/....

Verificação manual do mesmo que o check-linkage.sh faz — só devem aparecer bibliotecas de /usr/lib:

otool -L agent/httrack-agent

Estado da validação

Em macOS 26.6 / Apple Silicon / Xcode 26.6, sobre o HTTrack 3.49.14:

Verificação Resultado
configure + make exit 0; libhttrack.a com 4,0 MB
Link estático Só /usr/lib/libz, /usr/lib/libiconv, libSystem. 6,0 MB
Execução HTTrack version 3.49-14
HTTPS real Espelhou https://example.com/ sem erros nem avisos
make -C agent check Cinco suítes verdes: test-json, test-secrets, integração, parada/retomada e TLS
swift test 127 testes verdes, sem avisos — inclui um fim a fim que espelha, para e retoma contra o servidor de fixtures
scripts/assemble-app.sh MacHTTrack.app monta e assina; espelha, para e retoma pela interface

Aviso de segurança: TLS não autentica

O HTTrack não valida certificados TLS — é decisão do upstream (htslib.c:5731: "no cert verify, by design"), e nenhuma função de verificação aparece em src/*.c.

Na prática: https:// garante que o tráfego é criptografado, mas não que o servidor do outro lado seja quem diz ser. Um intermediário com certificado autoassinado é aceito em silêncio. Por isso o MacHTTrack não exibe cadeado nem usa a palavra "seguro" em lugar nenhum da interface — seria uma promessa que o motor não cumpre.

Esse comportamento está travado por agent/tests/test_tls.sh: se uma versão futura do motor passar a rejeitar certificados autoassinados, o teste falha — não porque rejeitar seja errado, mas porque a exigência de interface acima deixaria de valer e precisa ser revista, não descoberta por acaso.

Licença

O HTTrack é GPL-3.0-or-later. Este projeto o vincula estaticamente, então herda a GPL-3.0-or-later.

About

Interface gráfica nativa de macOS para o HTTrack Website Copier

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages