addFile method

void addFile(
  1. ArchiveFile file, {
  2. bool autoClose = true,
})
inherited

Implementation

void addFile(ArchiveFile file, {bool autoClose = true}) {
  final fileData = _ZipFileData();
  _data.files.add(fileData);

  final lastModMS = file.lastModTime * 1000;
  final lastModTime = DateTime.fromMillisecondsSinceEpoch(lastModMS);

  fileData.name = file.name;
  // If the archive modification time was overwritten, use that, otherwise
  // use the lastModTime from the file.
  fileData.time = _data.time ?? _getTime(lastModTime)!;
  fileData.date = _data.date ?? _getDate(lastModTime)!;
  fileData.mode = file.mode;
  fileData.isFile = file.isFile;

  InputStreamBase? compressedData;
  int crc32 = 0;

  // If the user want's to store the file without compressing it,
  // make sure it's decompressed.
  if (!file.compress) {
    if (file.isCompressed) {
      file.decompress();
    }

    compressedData = (file.content is InputStreamBase)
        ? file.content as InputStreamBase
        : InputStream(file.content);

    if (file.crc32 != null) {
      crc32 = file.crc32!;
    } else {
      crc32 = getFileCrc32(file);
    }
  } else if (file.isCompressed &&
      file.compressionType == ArchiveFile.DEFLATE &&
      file.rawContent != null) {
    // If the file is already compressed, no sense in uncompressing it and
    // compressing it again, just pass along the already compressed data.
    compressedData = file.rawContent;

    if (file.crc32 != null) {
      crc32 = file.crc32!;
    } else {
      crc32 = getFileCrc32(file);
    }
  } else if (file.isFile) {
    // Otherwise we need to compress it now.
    crc32 = getFileCrc32(file);

    dynamic bytes = file.content;
    if (bytes is InputStreamBase) {
      bytes = bytes.toUint8List();
    }
    bytes = Deflate(bytes as List<int>, level: _data.level).getBytes();
    compressedData = InputStream(bytes);
  }

  final encodedFilename = filenameEncoding.encode(file.name);
  final comment =
      file.comment != null ? filenameEncoding.encode(file.comment!) : null;

  Uint8List? salt;

  if (password != null && compressedData != null) {
    // https://www.winzip.com/en/support/aes-encryption/#zip-format
    //
    // The size of the salt value depends on the length of the encryption key,
    // as follows:
    //
    // Key size Salt size
    // 128 bits  8 bytes
    // 192 bits 12 bytes
    // 256 bits 16 bytes
    //
    salt = _generateSalt(16);

    final encryptedBytes =
        _encryptCompressedData(compressedData.toUint8List(), salt);

    compressedData = InputStream(encryptedBytes);
  }

  final dataLen = (compressedData?.length ?? 0) +
      (salt?.length ?? 0) +
      (_mac?.length ?? 0) +
      (_pwdVer?.length ?? 0);

  _data.localFileSize += 30 + encodedFilename.length + dataLen;

  _data.centralDirectorySize +=
      46 + encodedFilename.length + (comment != null ? comment.length : 0);

  fileData.crc32 = crc32;
  fileData.compressedSize = dataLen;
  fileData.compressedData = compressedData;
  fileData.uncompressedSize = file.size;
  fileData.compress = file.compress;
  fileData.comment = file.comment;
  fileData.position = _output!.length;

  _writeFile(fileData, _output!, salt: salt);

  fileData.compressedData = null;

  if (autoClose) {
    file.closeSync();
  }
}