# Ficheros de Mac clásico

> Implementado (fase 6). **Funciona de forma transparente** en todos los shares;
> `Mac = false` lo desactiva en un share concreto.

## El problema

En Mac OS clásico (System 6 a Mac OS 9) un fichero tiene:

- **Data fork:** el contenido "normal".
- **Resource fork:** recursos. En aplicaciones y muchos documentos es imprescindible.
- **Información del Finder:** tipo y creador (4 caracteres cada uno), indicadores, posición.

Windows y Linux solo guardan el *data fork*. Si un fichero de Mac pasa por un servidor normal,
pierde el resto y deja de funcionar. Por eso en esa época se viajaba **codificado**:

- **MacBinary** (`.bin`): binario, una cabecera de 128 bytes y después los dos forks.
- **BinHex 4.0** (`.hqx`): texto de 7 bits, apto incluso para correo.

## Por qué puede ser transparente

- **Detectar MacBinary II/III y BinHex es fiable**, porque llevan CRC: un fichero que no lo es
  prácticamente nunca pasa la comprobación por casualidad.
- **El fichero decodificado se puede volver a codificar sin pérdida:** el *data fork* queda como
  fichero normal y el resto se guarda aparte.
- **Si el fichero no tiene nada propio de Mac, no se toca.**

Por eso no hace falta activarlo. `Mac = false` solo tiene sentido en shares que guardan
`.bin`/`.hqx` como archivo (p. ej. una colección de software para emuladores), donde se quiere
conservar el fichero codificado tal cual.

## Almacenamiento: AppleDouble

Cada fichero de Mac se guarda como:

- `nombre`: el *data fork*, usable desde cualquier sistema;
- `._nombre`: fichero **AppleDouble** (versión 2) en la misma carpeta, con la entrada 9 (Finder
  Info, 32 bytes) y la entrada 2 (Resource Fork).

Es el mismo formato que usa macOS en volúmenes que no admiten forks (FAT, SMB…), así que es
compatible con macOS moderno y con otras herramientas.

- Los `._*` que acompañan a un fichero, `.DS_Store` e `Icon\r` no se muestran en los listados
  (web, FTP, WebDAV).
- Renombrar, mover o borrar un fichero hace lo mismo con su `._`.

## Subir

Por formulario web, por la subida por trozos de la página moderna (`PUT` con `X-Sunfish-Upload`) o por FTP (`STOR`):

| Llega | Se decodifica si… | Se guarda |
|---|---|---|
| MacBinary II/III | byte 0 y 74 a cero, longitud de nombre 1–63, longitudes de los forks coherentes y **CRC-16 de la cabecera correcto** (III: firma `mBIN` en el desplazamiento 102) | `nombre` + `._nombre` |
| MacBinary I | Sin CRC: solo si el cliente tiene perfil `mac`, el fichero acaba en `.bin` y la cabecera es coherente | `nombre` + `._nombre` |
| BinHex 4.0 | Línea `(This file must be converted with BinHex 4.0)` y CRC de las tres partes correctos | `nombre` + `._nombre` |
| Cualquier otra cosa | — | tal cual |

- El nombre se toma de la cabecera (MacRoman → Unicode).
- Si el fichero no tenía *resource fork* ni información relevante del Finder, no se crea el `._`.
- Si el nombre decodificado ya existe y el share no tiene `Overwrite`, **se conserva el fichero
  codificado** tal como llegó (no se pierde nada) y el registro lo avisa. Con `Overwrite`, se
  sustituye.
- Un `PUT` de WebDAV normal **no se decodifica**: los clientes WebDAV modernos (Finder, Windows)
  ya escriben los forks como `._` por su cuenta, y un `.bin` copiado así se quiere tal cual.
- BinHex se decodifica en memoria: solo hasta 256 MB.

## Descargar

- **Cliente con perfil `mac`** ([CLIENTES.md](CLIENTES.md)), fichero con `._`: la descarga normal
  se entrega **en MacBinary automáticamente** (`application/x-macbinary`). El decodificador del
  navegador (o el que tenga asociado) restaura los forks sin que el usuario haga nada.
- **Cliente con perfil `mac`, fichero sin `._`:** se entrega tal cual. El Mac asigna tipo y
  creador por su tabla de extensiones.
- **Cualquier otro cliente:** recibe el *data fork*. Si el fichero tiene `._`, el listado lo
  marca y ofrece enlaces explícitos:
  - `[.bin]` → `fichero?as=macbin`, MacBinary III (también lo leen los decodificadores de
    MacBinary II);
  - `[.hqx]` → `fichero?as=hqx`, `application/mac-binhex40`.

Al codificar:

- *data fork* = el fichero; *resource fork* e información del Finder = su `._`;
- si no hay `._` (enlaces explícitos), tipo y creador salen de una **tabla por extensión** (p. ej.
  `.txt` → `TEXT`, `.gif` → `GIFf`, `.jpg` → `JPEG`, `.sit` → `SIT!`, `.pdf` → `PDF `). **Pendiente:**
  ampliarla
  con una sección `[MacTypes]` en la configuración (aún no existe);
- el nombre se convierte a MacRoman y se acorta a 31 caracteres (límite de HFS), conservando la
  extensión.

Para FTP, ver [FTP-Y-WEBDAV.md](FTP-Y-WEBDAV.md#nombres-cortos-y-mac-en-ftp).

## Fuera de alcance

- StuffIt (`.sit`) y otros formatos comprimidos de Mac: se tratan como ficheros normales.
- Conversión de saltos de línea `CR` de los ficheros de texto de Mac (lo hace el cliente o el
  modo `TYPE A` de FTP).

## Pruebas

En `tests/Sunfish.Tests/MacTests.cs`:

- MacBinary III de ida y vuelta (forks, tipo, creador, fecha), CRC alterado y falsos positivos
  (datos aleatorios, un `.bin` cualquiera queda intacto).
- BinHex de ida y vuelta con bytes `0x90` (RLE) y CRC alterado.
- AppleDouble de ida y vuelta; el `._` sigue al fichero al mover y borrar.
- Decodificación al subir y conservación del codificado si el nombre ya existe.
- Servidor real: enlaces `[.bin]`/`[.hqx]`, `?as=macbin`/`?as=hqx`, entrega automática al perfil
  `mac`, subida por formulario que se decodifica, FTP `+mac` (`nombre.bin` en el listado, `SIZE`,
  `RETR`, `STOR` que se decodifica).
- Probado también con el binario AOT: subida MacBinary por FTP, separación en `nombre` + `._nombre`
  y descarga `.bin` idéntica byte a byte.
- **Sin probar** con un Mac clásico real ni con `._` generados por macOS moderno.
