# Compilación, pruebas y estado

## Estado actual

- **Fase 1 (hecha):** `Sunfish.Core` con configuración INI (conserva comentarios), shares y
  locations, validación de rutas, motor HTTP propio (0.9/1.0/1.1, keep-alive, rangos, 304) y
  web de solo lectura (índice, `?$list`, navegador de directorios clásico/moderno/texto, perfiles
  de cliente, recursos GIF, autodescarga). `sunfish-cli` con `serve` y modo rápido, sin TUI.
  Probado en un navegador moderno y con peticiones de cliente antiguo.
- **Fase 2 (hecha):** escritura web. Subida por formulario multipart (lector en flujo, campos
  `a`/`t` antes del fichero) y `PUT` por trozos (`Content-Range` + `X-Sunfish-Upload`), crear
  carpeta, renombrar y borrar con página de confirmación, *tokens* anti-CSRF sin cookies,
  usuarios con HTTP Basic (PBKDF2, caché y bloqueo por intentos), ZIP en flujo (Stored, CRC
  previo, `Content-Length`; nombres CP437 para clientes antiguos y UTF-8 para modernos).
  `sunfish-cli user add|passwd|del|list`. `dotnet test`: 140 pruebas en verde. AOT win-x64:
  ~3,8 MB sin avisos. Probado en un navegador moderno (arrastrar y soltar, borrado con
  confirmación), con usuario y contraseña, y ZIP descargado como cliente antiguo.
- **Fase 3 (hecha):** aplicaciones.
  - `Sunfish.exe` (WinForms): interruptor y puerto, lista de shares con activar/desactivar,
    alta (también arrastrando carpetas a la ventana o sobre el `.exe`), edición, borrado, menú
    con abrir en el navegador y copiar URL por IP, usuarios, registro, área de notificación e
    instancia única (una segunda instancia pasa sus carpetas a la primera por una tubería).
  - TUI de `sunfish-cli` (pestañas Estado con icono, Shares, Usuarios y Registro; formularios
    y preguntas en recuadros) y subcomandos `share add|set|del|list`.
  - `SunfishHost`: reinicio al cambiar de puerto, guardado y recarga del fichero si lo cambia
    otro programa (conservando las opciones de línea de comandos como `-p`).
  - Scripts `build.ps1`, `build.sh`, `run.cmd`, `run-cli.cmd` y `run.sh`.
  - `dotnet test`: 149 pruebas en verde.
  - **Tamaños medidos (win-x64):** `Sunfish.exe` autocontenido ~49 MB, ligero ~0,5 MB;
    `sunfish-cli.exe` AOT ~3,9 MB.
  - Probado: GUI en modo rápido, paso de carpetas desde una segunda instancia y alta de share
    (automatizado con UI Automation), TUI dibujada en Windows Terminal, subcomandos `share` y
    recarga en caliente con `serve`. `build.ps1` y `build.sh` se han comprobado solo en sintaxis
    (ejecutarlos hace `git pull`); las publicaciones que lanzan sí se han ejecutado a mano.
  - Después: TUI con marco Unicode y GUI con el aspecto de la 2.0 (ver
    [APLICACIONES.md](APLICACIONES.md)).
- **Fase 4 (hecha):** servidor FTP ([FTP-Y-WEBDAV.md](FTP-Y-WEBDAV.md)): pasivo y activo,
  anónimo y usuarios, `LIST`/`NLST`/`MLSD`/`MLST`, `RETR`/`STOR`/`APPE`/`REST`, carpetas,
  renombrar y mover, borrar, `SIZE`/`MDTM`, `TYPE A`, juegos de caracteres antiguos, perfiles por
  sufijo de usuario o `SITE PROFILE`, `ABOR`. El host arranca y para HTTP y FTP por separado y
  comparte con la web el bloqueo por intentos fallidos. GUI (fila «FTP en puerto»), TUI (teclas
  F y T) y `serve` muestran las direcciones `ftp://`. `dotnet test`: 173 pruebas en verde.
  AOT win-x64: ~4,1 MB. Probado con `curl` y con `ftp.exe` de Windows en modo activo.
- **Fase 5 (hecha):** WebDAV en el servidor (clase 1 + LOCK simulado), cliente WebDAV en el
  núcleo, DNS-SD sobre mDNS (anuncio y búsqueda), ventana «Explorar otro servidor» en la GUI y
  pestaña Explorar (F4) en la TUI ([FTP-Y-WEBDAV.md](FTP-Y-WEBDAV.md)). `dotnet test`: 189 pruebas
  en verde (incluida una búsqueda mDNS real que se salta si el 5353 no está disponible). AOT
  win-x64: ~8,3 MB. Probado con el redirector WebDAV de Windows (leer y escribir) y con la ventana
  Explorar de la GUI contra el propio servidor.
- La prueba de enlaces simbólicos se salta sola en Windows sin permiso para crearlos.
- Sin probar con navegadores ni clientes FTP antiguos reales, ni en Linux/macOS (GVfs, Finder,
  Avahi, Bonjour); las teclas de la TUI (incluida la pestaña Explorar) no se han probado de forma
  automática.
- **Fase 6 (hecha):** Mac clásico y nombres cortos ([MAC-CLASICO.md](MAC-CLASICO.md),
  [CLIENTES.md](CLIENTES.md)). MacBinary I/II/III, BinHex 4.0 y AppleDouble en `Sunfish.Core/Mac`;
  las subidas (formulario, PUT por trozos, `STOR`) se decodifican; descarga en MacBinary
  automática para el perfil `mac` y enlaces `[.bin]`/`[.hqx]` para los demás; FTP `+mac` con
  `nombre.bin`. Alias 8.3 estables (`Shares/ShortNames.cs`) en listados, enlaces, descargas y FTP
  `+dos`/`+win16`; las rutas se resuelven también por alias. El `._` sigue al fichero al
  renombrar, mover y borrar. `dotnet test`: 210 pruebas en verde. AOT win-x64: ~8,4 MB, sin
  avisos. Probado con el binario AOT por web y FTP (`curl`).
- **Fase 7 (hecha):** panel de administración web (`Web/WebAdmin.cs`, [WEB.md](WEB.md)),
  `AllowFrom` con redes CIDR (`Net/AddressRules.cs`), importación de la 2.0
  (`Config/LegacyImport.cs`, [SHARES-Y-RUTAS.md](SHARES-Y-RUTAS.md)) y generador de QR propio
  (`Qr/`, [APLICACIONES.md](APLICACIONES.md)). GUI: ventana de QR, diálogo del panel web e
  importación al crear la configuración. CLI: `admin`, `import-v2` y tecla C (QR) en la TUI.
  `dotnet test`: 252 pruebas en verde; el QR se comprueba leyéndolo con ZXing.Net (dependencia
  solo del proyecto de pruebas). AOT win-x64: ~8,7 MB, sin avisos. Probado con el binario AOT:
  `import-v2`, `admin enable/allow/status`, el panel con `curl` (401/200, QR, guardar que
  reinicia FTP sin cortar HTTP) y en un navegador.
- **Siguiente (sin fase asignada):** conexiones activas, iniciar con Windows, servicio de
  Windows, regla del cortafuegos; pruebas con clientes antiguos reales.
- El código de la 2.0 se retiró; queda en la etiqueta `2.0` ([LEGACY-2.0.md](LEGACY-2.0.md)).
- Rama actual `master` en un remoto privado. El README ya da las instrucciones para GitHub
  (rama `main`), para cuando se publique allí.

## Publicación prevista

| Proyecto | Salida | Propiedades |
|---|---|---|
| `Sunfish.Core` | biblioteca | `IsAotCompatible`, `TreatWarningsAsErrors` para avisos de AOT/trimming |
| `Sunfish.Cli` | `sunfish-cli` / `sunfish-cli.exe` | `PublishAot`, `InvariantGlobalization`, `StripSymbols` |
| `Sunfish.WinForms` | `Sunfish.exe` | `OutputType=WinExe`, `UseWindowsForms`, `PublishSingleFile`, `IncludeNativeLibrariesForSelfExtract`; autocontenido + `EnableCompressionInSingleFile` o dependiente del framework (pendiente, ver [ARQUITECTURA.md](ARQUITECTURA.md#publicación)) |

- .NET 10. RID: `win-x64`, `win-arm64`, `linux-x64`, `linux-arm64`, `osx-x64`, `osx-arm64`.
- Native AOT no compila de forma cruzada entre sistemas: cada `sunfish-cli` se compila en su
  sistema.

## Requisitos

- git y el SDK de .NET 10.
- Para `sunfish-cli` (AOT):
  - Windows: Visual Studio Build Tools con «Desarrollo para escritorio con C++».
  - Linux: `clang`, `ld` y las cabeceras de zlib.
  - macOS: Xcode Command Line Tools.
- Para `Sunfish.exe`: solo el SDK.

## Scripts previstos

| Script | Función |
|---|---|
| `build.ps1` | Windows. Detecta el RID, comprueba requisitos (no instala nada; da el comando), usa el repo actual o clona/actualiza, publica `Sunfish.exe` y `sunfish-cli.exe`, los deja en la raíz y explica cómo poner `sunfish-cli` en el `PATH`. **Pendiente:** si faltan las herramientas de C++, ¿falla o compila solo la GUI? |
| `build.sh` | Linux y macOS. Lo mismo para `sunfish-cli` (sugerencias para apt, dnf, pacman y brew) |
| `run.cmd` | `dotnet run` de `Sunfish.WinForms`, para doble clic |
| `run-cli.cmd` | `dotnet run` de `Sunfish.Cli`, para doble clic |
| `run.sh` | `dotnet run` de `Sunfish.Cli` en Linux y macOS |

- Variable para forks: `SUNFISH_REPO_URL`.
- Sin script `publish` aparte: `build.*` ya publica.
- `.gitignore`: `/Sunfish.exe`, `/sunfish-cli`, `/sunfish-cli.exe`, `/sunfish.conf`, `publish/`.

## Comandos previstos

```
dotnet build
dotnet test
dotnet run --project src/Sunfish.WinForms
dotnet run --project src/Sunfish.Cli -- [argumentos]
dotnet publish src/Sunfish.Cli -c Release -r <RID>
dotnet publish src/Sunfish.WinForms -c Release -r win-x64
```

## Pruebas automáticas previstas (`tests/Sunfish.Tests`)

xUnit sobre `net10.0`, con `InternalsVisibleTo` desde `Sunfish.Core`. Las pruebas que tocan
variables de entorno van en una colección sin paralelismo. Las de servidor arrancan
`SunfishHost` en `localhost` con puertos libres y hablan con él por sockets.

| Área | Qué se prueba |
|---|---|
| HTTP | HTTP/0.9, 1.0 sin `Host`, `LF` solo, cabeceras raras, límites, keep-alive, `chunked`, `Range`, 304, `HEAD` |
| Multipart | Límites partidos entre búferes, varios ficheros, nombres con ruta de Windows o de Mac, subida cortada (no deja restos) |
| Locations | Prefijo más largo, comparación por segmentos, ocultación, directorios virtuales, raíz con y sin menú, `/$sunfish` |
| Rutas | `..`, `%2e%2e`, `\`, `:`, nombres reservados, enlaces que salen del share (con ramas por SO) |
| Permisos | Matriz operación × opción de share × web/FTP/WebDAV; usuarios |
| HTML | Escapado, entidades Latin-1, enlaces `%XX` en UTF-8, modo clásico sin `<script>` |
| CSRF / Auth | *Tokens* válidos, caducados y de otra ruta; PBKDF2; caché; bloqueo por intentos |
| FTP | Comandos, `LIST` en formato `ls -l`, `MLSD`, `PASV`/`EPSV`, `PORT` hacia otra IP rechazado, `REST`, `TYPE A`, juegos de caracteres |
| WebDAV | `PROPFIND` 0/1, `infinity` rechazado, `MKCOL`, `MOVE`/`COPY`, `LOCK` simulado, XML con DTD rechazado |
| Mac | Ver [MAC-CLASICO.md](MAC-CLASICO.md#pruebas-previstas) |
| ZIP | Lo generado se lee con `System.IO.Compression`; Stored y Deflate; nombres CP437/UTF-8 |
| Config | Lectura, escritura conservando comentarios, errores con línea, importación de `sunfish2` |
| QR | Matrices frente a vectores de referencia |
| Clientes | Perfil por User-Agent, `?p=` propagado en los enlaces, sufijos `+dos`/`+mac` y `SITE PROFILE` en FTP |
| Alias 8.3 | Estabilidad al añadir y quitar ficheros, colisiones, transliteración, resolución alias → nombre real |
| `?$list` | Listado con índice presente, sin `Listing`, y webs con sus propios parámetros |
| DNS-SD | Formato de los anuncios y respuestas mDNS |
| Cliente WebDAV | Contra el propio servidor: listar, copiar en los dos sentidos, renombrar |

## Pruebas manuales previstas

- **Navegadores modernos:** web clásica y moderna, arrastrar y soltar, subida grande por trozos.
- **DOS** con *packet driver*: navegador de texto y gráfico, cliente FTP y descargador HTTP de
  línea de comandos; comprobar alias 8.3 y CP437.
- **Windows 3.1 / WfW 3.11** con pila Winsock: navegadores de 16 bits (listado, descargas con
  alias 8.3, subida por formulario donde se admita) y cliente FTP de 16 bits.
- **Windows 95/98** con sus navegadores de la época: listado, descargas, subidas por formulario,
  ZIP; `ftp.exe` en modo activo; Carpetas web (WebDAV).
- **Mac clásico (System 6/7, Mac OS 8/9)** con navegadores y clientes FTP de la época: listado,
  descargas `.bin`/`.hqx`, subidas MacBinary/BinHex, nombres con acentos.
- **WebDAV moderno:** Explorador de Windows, Finder de macOS, GVfs.
- **GUI:** doble clic, arrastrar carpeta a la lista y sobre el `.exe`, bandeja, instancia única.
- **TUI** en Windows Terminal, conhost, Linux, macOS y por SSH; icono visible u oculto según el
  tamaño, y en 16, 256 y color real.
- **Sunfish a Sunfish:** descubrimiento en la LAN y copia en los dos sentidos.
- `build.ps1` con `| iex`; `build.sh` en Linux y macOS.
