Patch title: Release 85 bulk changes
Abstract:
File: /pliant/protocol/smtp/mime.pli
Key:
    Removed line
    Added line
module "/pliant/language/unsafe.pli"
module "/pliant/language/stream.pli"
module "/pliant/util/encoding/base64.pli"
module "/pliant/util/encoding/qp.pli"


function ms_decode l
  arg_rw Str l
  if (l eparse any:(var Str head) "=?" any:(var Str charset) "?" any:(var Str enc) "?" any:(var Str value) "?=" any:(var Str tail))
    if lower:enc="q"
      ms_decode tail
      l := head+qp_decode:value+tail
    eif lower:enc="b"
      ms_decode tail
      l := head+base64_decode:value+tail


type MimeStream
  field Pointer:Stream stream
  field Str name
  field Str mime encoding
  field CBool embedded <- false
  field CBool html <- false
  field CBool spam <- false
  field Int encoding_model <- 0
  field List:Str boundaries
  field Str ready

method ms multipart -> c
  arg MimeStream ms ; arg CBool c
  c := (exists ms:boundaries:first) or ms:embedded

method ms bind s reset
  arg_rw MimeStream ms ; arg_rw Stream s ; arg CBool reset
  ms stream :> s
  ms name := ""
  ms mime := ""
  ms embedded := false
  ms html := false
  ms encoding_model := 0
  ms ready := ""
  if reset
    ms boundaries := var List:Str empty_list
    ms spam := false

method ms header_line l -> c
  arg_rw MimeStream ms ; arg_w Str l ; arg CBool c
  l := ms:stream readline
  if l=""
    return false
  while not ms:stream:atend and { var Char ch := ms:stream:stream_read_cur map Char ; ch=" " or ch="[tab]" }
    l += ms:stream readline
  if (l parse acword:"content-type" ":" any:(var Str value) ";" any)
    ms mime := value
  eif (l parse acword:"content-type" ":" any:(var Str value))
    ms mime := value
  if (l parse acword:"content-transfer-encoding" ":" any:(var Str value) ";" any)
    ms encoding := value
  eif (l parse acword:"content-transfer-encoding" ":" any:(var Str value))
    ms encoding := value
  if (l parse acword:"content-type" ":" acword:"message" any)
    ms embedded := true
  if (l parse acword:"content-type" ":" acword:"text" "/" word:"html" any)
    ms html := true
  if (l parse acword:"content-type" ":" acword:"multipart" any acword:"boundary" "=" "[dq]" any:(var Str value) "[dq]" any)
    ms boundaries += value
  eif (l parse acword:"content-type" ":" acword:"multipart" any acword:"boundary" "=" any:(var Str value))
    ms boundaries += value
  if (l parse acword:"content-transfer-encoding" ":" any acword:"base64" any)
    ms encoding_model := 1
  eif (l parse acword:"content-transfer-encoding" ":" any acword:"quoted-printable" any)
    ms encoding_model := 2
  eif (l parse acword:"content-transfer-encoding" ":" any)
    ms encoding_model := undefined
  if l="spam"
    ms spam := true
  # Novell unstandard encoding_model
  if (l parse acword:"content-disposition" ":" any acword:"filename" "=" "[dq]" any:(var Str value) "[dq]" any)
    ms_decode value
    ms name := value
  if (l parse acword:"content-type" ":" any acword:"name" "=" "[dq]" any:(var Str value) "[dq]" any)
    ms_decode value # cope with crazy Microsoft encoding_model
    ms name := value
  c := true


method ms body_line l -> c
  arg_rw MimeStream ms ; arg_w Str l ; arg CBool c
  if ms:ready:len>0
    l := ms ready
    ms ready := ""
    return true
  if ms:stream:atend
    return false
  l := ms:stream readline
  if (l 0 2)="--"
    var Pointer:Str b :> ms:boundaries first
    while exists:b
      if l="--"+b or l="--"+b+"--"
        return false
      b :> ms:boundaries next b
  if ms:encoding_model=1 # base64
    l := base64_decode l
  eif ms:encoding_model=2 # quoted printable
    if l:len>0 and (l l:len-1)="="
      l := qp_decode (l 0 l:len-1)
    else
      l := qp_decode:l+"[lf]"
  else
    l += "[lf]"
  if ms:embedded  
    while not ms:stream:atend and { var Char ch := ms:stream:stream_read_cur map Char ; ch=" " or ch="[tab]" }
      l += ms:stream readline
    if (l parse acword:"content-type" ":" acword:"multipart" any acword:"boundary" "=" "[dq]" any:(var Str value) "[dq]" any)
      ms boundaries += value
    eif (l parse acword:"content-type" ":" acword:"multipart" any acword:"boundary" "=" any:(var Str value))
      ms boundaries += value
    if l=""
      ms embedded := false
  c := true

method ms unread l
  arg_rw MimeStream ms ; arg Str l
  ms ready := l

export ms_decode
export MimeStream '. bind'
export '. name' '. mime' '. encoding' '. encoding_model' '. multipart' '. html' '. spam'
export '. header_line' '. body_line' '. unread'