mirror of
https://github.com/mjl-/mox.git
synced 2025-07-19 03:26:37 +03:00
implement the imap metadata extension, rfc 5464
this allows setting per-mailbox and per-server annotations (metadata). we have a fixed maximum for total number of annotations (1000) and their total size (1000000 bytes). this size isn't held against the regular quota for simplicity. we send unsolicited metadata responses when a connection is in the idle command and a change to a metadata item is made. we currently only implement the /private/ namespace. we should implement the /shared/ namespace, for mox-global metadata annotations. only the admin should be able to configure those, probably through the config file, cli, or admin web interface. for issue #290
This commit is contained in:
@ -305,10 +305,10 @@ func (p *parser) xstring() (r string) {
|
||||
p.xerrorf("missing closing dquote in string")
|
||||
}
|
||||
size, sync := p.xliteralSize(false, true)
|
||||
s := p.conn.xreadliteral(size, sync)
|
||||
buf := p.conn.xreadliteral(size, sync)
|
||||
line := p.conn.readline(false)
|
||||
p.orig, p.upper, p.o = line, toUpper(line), 0
|
||||
return s
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
func (p *parser) xnil() {
|
||||
@ -974,3 +974,53 @@ func (p *parser) xdate() time.Time {
|
||||
}
|
||||
return time.Date(year, mon, day, 0, 0, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
// Parse and validate a metadata key (entry name), returned as lower-case.
|
||||
//
|
||||
// ../rfc/5464:190
|
||||
func (p *parser) xmetadataKey() string {
|
||||
// ../rfc/5464:772
|
||||
s := p.xastring()
|
||||
|
||||
// ../rfc/5464:192
|
||||
if strings.Contains(s, "//") {
|
||||
p.xerrorf("entry name must not contain two slashes")
|
||||
}
|
||||
// We allow a single slash, so it can be used with option "(depth infinity)" to get
|
||||
// all annotations.
|
||||
if s != "/" && strings.HasSuffix(s, "/") {
|
||||
p.xerrorf("entry name must not end with slash")
|
||||
}
|
||||
// ../rfc/5464:202
|
||||
if strings.Contains(s, "*") || strings.Contains(s, "%") {
|
||||
p.xerrorf("entry name must not contain * or %%")
|
||||
}
|
||||
for _, c := range s {
|
||||
if c < ' ' || c >= 0x7f {
|
||||
p.xerrorf("entry name must only contain non-control ascii characters")
|
||||
}
|
||||
}
|
||||
return strings.ToLower(s)
|
||||
}
|
||||
|
||||
// ../rfc/5464:776
|
||||
func (p *parser) xmetadataKeyValue() (key string, isString bool, value []byte) {
|
||||
key = p.xmetadataKey()
|
||||
p.xspace()
|
||||
|
||||
if p.hasPrefix("~{") {
|
||||
size, sync := p.xliteralSize(true, true)
|
||||
value = p.conn.xreadliteral(size, sync)
|
||||
line := p.conn.readline(false)
|
||||
p.orig, p.upper, p.o = line, toUpper(line), 0
|
||||
} else if p.hasPrefix(`"`) {
|
||||
value = []byte(p.xstring())
|
||||
isString = true
|
||||
} else if p.take("NIL") {
|
||||
value = nil
|
||||
} else {
|
||||
p.xerrorf("expected metadata value")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user