| 1 | The basic idea is that the database file is an append-only journal. |
|---|
| 2 | For now, there is no "vacuum" or "expire". The file SHOULD NOT be |
|---|
| 3 | edited, only appened to. |
|---|
| 4 | |
|---|
| 5 | The file is a line-oriented text file. A record consists of a |
|---|
| 6 | transaction start line, followed by a record description line, then |
|---|
| 7 | zero or more dot-stuffed lines (in the style of RFC 3977), and finally |
|---|
| 8 | a transaction end line. The idea is that a truncated record can (and |
|---|
| 9 | MUST) always be detected and ignored. |
|---|
| 10 | |
|---|
| 11 | Lines end with either LF or CRLF. Readers MUST be able to handle both |
|---|
| 12 | formats, and convert between them when required for other media (for |
|---|
| 13 | example, NNTP requires CRLF, and so any LF neeeds to be converted to |
|---|
| 14 | CRLF before sending over NNTP). |
|---|
| 15 | |
|---|
| 16 | WARNING: The format is not safe for concurrent writing. |
|---|
| 17 | |
|---|
| 18 | A record starts with the line |
|---|
| 19 | .BEGIN <datetime> |
|---|
| 20 | where <datetime> is in ISO format (yyyymmddThhmmss) and in UTC, indicating the |
|---|
| 21 | timestamp of the record. |
|---|
| 22 | |
|---|
| 23 | A record ends with the line |
|---|
| 24 | .END |
|---|
| 25 | |
|---|
| 26 | Empty lines between records must be ignored. |
|---|
| 27 | |
|---|
| 28 | |
|---|
| 29 | USER records |
|---|
| 30 | |
|---|
| 31 | .BEGIN <datetime> |
|---|
| 32 | USER <userid> |
|---|
| 33 | <attribute> <value> |
|---|
| 34 | .END |
|---|
| 35 | |
|---|
| 36 | USER MUST NOT be repeated inside the same record. |
|---|
| 37 | |
|---|
| 38 | The attribute lines MAY be repeated and MAY be omitted. |
|---|
| 39 | |
|---|
| 40 | Possible <attributes>: |
|---|
| 41 | - display_name (string) |
|---|
| 42 | - display_email (string) |
|---|
| 43 | - delivery_email (string) |
|---|
| 44 | - delivery_email_verified ("yes" / "no") [default: no] |
|---|
| 45 | - delivery_email_cookie (string) |
|---|
| 46 | - allow_cleartext_password ("yes" / "no") |
|---|
| 47 | - has_read (string: msgid) |
|---|
| 48 | - has_not_read (string: msgid) |
|---|
| 49 | |
|---|
| 50 | If the userid doesn't yet exist, it is created with the given |
|---|
| 51 | settings. If it exists, the included setting changes are made. |
|---|
| 52 | |
|---|
| 53 | |
|---|
| 54 | ROLE records |
|---|
| 55 | |
|---|
| 56 | .BEGIN <datetime> |
|---|
| 57 | ROLE <name> |
|---|
| 58 | DESCRIPTION <description> |
|---|
| 59 | USER ADD <userid> |
|---|
| 60 | USER DEL <userid> |
|---|
| 61 | .END |
|---|
| 62 | |
|---|
| 63 | The ROLE line is REQUIRED and MUST NOT be repeated. |
|---|
| 64 | The other lines are OPTIONAL. |
|---|
| 65 | USER lines may be repeated. |
|---|
| 66 | |
|---|
| 67 | If the role doesn't exist yet, it is created with the given settings. |
|---|
| 68 | If it exists, the included setting changes are made. |
|---|
| 69 | |
|---|
| 70 | NOTE: The following role names are reserved: anonymous, authenticated, |
|---|
| 71 | poster. Similarly, all names starting with "subscribers:" and |
|---|
| 72 | "moderator:" are reserved. No ROLE records may be given for |
|---|
| 73 | "anonymous" and "authenticated". ROLE records for the other reserved |
|---|
| 74 | names are forbidden to include DESCRIPTION. |
|---|
| 75 | |
|---|
| 76 | |
|---|
| 77 | NEWGROUP records |
|---|
| 78 | |
|---|
| 79 | .BEGIN <datetime> |
|---|
| 80 | NEWGROUP <groupname> |
|---|
| 81 | DESCRIPTION <group description for LIST NEWSGROUPS> |
|---|
| 82 | READING <permission-token> |
|---|
| 83 | .END |
|---|
| 84 | |
|---|
| 85 | The NEWGROUP MUST NOT be repeated. |
|---|
| 86 | |
|---|
| 87 | <permission-token> is PERMITTED | RESTRICTED (the latter meaning that |
|---|
| 88 | the group is available only to authenticated users) |
|---|
| 89 | |
|---|
| 90 | |
|---|
| 91 | ARTICLE records |
|---|
| 92 | |
|---|
| 93 | .BEGIN <datetime> |
|---|
| 94 | ARTICLE <msgid> |
|---|
| 95 | POSTED BY <userid> |
|---|
| 96 | FILE AS <groupname>:<article-number> |
|---|
| 97 | FOLLOWS |
|---|
| 98 | <article header and body> |
|---|
| 99 | .END |
|---|
| 100 | |
|---|
| 101 | The FILE AS line SHOULD occur at least once, and MAY occur multiple times. |
|---|
| 102 | POSTED BY is recommended but may be omitted. |
|---|
| 103 | The other lines are REQUIRED. |
|---|
| 104 | |
|---|
| 105 | The <article header and body> lines MUST be dot-stuffed as discussed |
|---|
| 106 | in RFC 3977. However, it ends in .END, not a lone dot line. |
|---|
| 107 | |
|---|
| 108 | The article SHOULD NOT contain a Xref header field; if there is one, |
|---|
| 109 | it MUST be ignored (and a new one generated based on the actual server |
|---|
| 110 | state). |
|---|
| 111 | |
|---|
| 112 | |
|---|
| 113 | MODERATION records |
|---|
| 114 | |
|---|
| 115 | .BEGIN <datetime> |
|---|
| 116 | MODERATION <userid> |
|---|
| 117 | <verb> <msgid> <reason> |
|---|
| 118 | .END |
|---|
| 119 | |
|---|
| 120 | <verb> ::= KILL |
|---|
| 121 | | SPAM |
|---|
| 122 | | CLEAR |
|---|
| 123 | |
|---|
| 124 | <reason> ::= <text not containing line terminator or separator> |
|---|
| 125 | |
|---|
| 126 | The MODERATION line is REQUIRED and MUST NOT be repeated. The other |
|---|
| 127 | lines MAY occur multiple times. The <userid> indicates the user who |
|---|
| 128 | authorized these moderation actions. |
|---|
| 129 | |
|---|
| 130 | The effect of a KILL or SPAM line is to make the message disappear |
|---|
| 131 | (the reason is free form text that is intended to be used as |
|---|
| 132 | rationale); it will be as if it never existed. The effect of a CLEAR |
|---|
| 133 | line is to undo a previous KILL or SPAM line. |
|---|