ParameterizedHeader constructor

ParameterizedHeader(
  1. String rawValue
)

Creates a new header with the given rawValue

Parameters are separated at ; outside of quoted strings, so a quoted value such as filename="a;b.txt" stays intact. RFC 2231 parameter continuations (name*0=, name*1=) and character set encoded values (name*=utf-8''%E2%82%AC.txt) are decoded into the plain parameter.

Implementation

ParameterizedHeader(this.rawValue) {
  final elements = _splitParameters(rawValue);
  value = elements.first.trim();
  final sections = <String, Map<int, String>>{};
  final charsets = <String, String?>{};
  for (var i = 1; i < elements.length; i++) {
    final element = elements[i].trim();
    if (element.isEmpty) {
      continue;
    }
    final splitPos = element.indexOf('=');
    if (splitPos == -1) {
      parameters[element.toLowerCase()] = '';
      continue;
    }
    var name = element.substring(0, splitPos).trim().toLowerCase();
    var value = removeQuotes(element.substring(splitPos + 1).trim());
    final isEncoded = name.endsWith('*');
    if (isEncoded) {
      name = name.substring(0, name.length - 1);
    }
    int? section;
    final sectionStart = name.lastIndexOf('*');
    if (sectionStart != -1) {
      section = int.tryParse(name.substring(sectionStart + 1));
      if (section != null) {
        name = name.substring(0, sectionStart);
      }
    }
    if (isEncoded) {
      var charset = charsets[name];
      if (section == null || section == 0) {
        // the first section carries charset'language'value
        final charsetEnd = value.indexOf("'");
        final languageEnd = charsetEnd == -1
            ? -1
            : value.indexOf("'", charsetEnd + 1);
        if (languageEnd != -1) {
          charset = value.substring(0, charsetEnd);
          charsets[name] = charset;
          value = value.substring(languageEnd + 1);
        }
      }
      value = _decodeRfc2231Value(value, charset);
    }
    if (section != null) {
      (sections[name] ??= <int, String>{})[section] = value;
    } else {
      parameters[name] = value;
    }
  }
  for (final entry in sections.entries) {
    final indices = entry.value.keys.toList()..sort();
    parameters[entry.key] = [
      for (final index in indices) entry.value[index]!,
    ].join();
  }
}