]>
Commit | Line | Data |
---|---|---|
6988a057 JH |
1 | package hotline |
2 | ||
72f8a1fd JH |
3 | import "fmt" |
4 | ||
6988a057 | 5 | const ( |
d9bc63a1 JH |
6 | AccessDeleteFile = 0 // File System Maintenance: Can Delete Files |
7 | AccessUploadFile = 1 // File System Maintenance: Can Upload Files | |
8 | AccessDownloadFile = 2 // File System Maintenance: Can Download Files | |
9 | AccessRenameFile = 3 // File System Maintenance: Can Rename Files | |
10 | AccessMoveFile = 4 // File System Maintenance: Can Move Files | |
11 | AccessCreateFolder = 5 // File System Maintenance: Can Create Folders | |
12 | AccessDeleteFolder = 6 // File System Maintenance: Can Delete Folders | |
13 | AccessRenameFolder = 7 // File System Maintenance: Can Rename Folders | |
14 | AccessMoveFolder = 8 // File System Maintenance: Can Move Folders | |
15 | AccessReadChat = 9 // Chat: Can Read Chat | |
16 | AccessSendChat = 10 // Chat: Can Send Chat | |
17 | AccessOpenChat = 11 // Chat: Can Initial Private Chat | |
18 | AccessCloseChat = 12 // Present in the Hotline 1.9 protocol documentation, but seemingly unused | |
19 | AccessShowInList = 13 // Present in the Hotline 1.9 protocol documentation, but seemingly unused | |
20 | AccessCreateUser = 14 // User Maintenance: Can Create Accounts | |
21 | AccessDeleteUser = 15 // User Maintenance: Can Delete Accounts | |
22 | AccessOpenUser = 16 // User Maintenance: Can Read Accounts | |
23 | AccessModifyUser = 17 // User Maintenance: Can Modify Accounts | |
24 | AccessChangeOwnPass = 18 // Present in the Hotline 1.9 protocol documentation, but seemingly unused | |
25 | AccessNewsReadArt = 20 // News: Can Read Articles | |
26 | AccessNewsPostArt = 21 // News: Can Post Articles | |
27 | AccessDisconUser = 22 // User Maintenance: Can Disconnect Users (Note: Turns username red in user list) | |
28 | AccessCannotBeDiscon = 23 // User Maintenance: Cannot be Disconnected | |
29 | AccessGetClientInfo = 24 // User Maintenance: Can Get User Info | |
30 | AccessUploadAnywhere = 25 // File System Maintenance: Can Upload Anywhere | |
31 | AccessAnyName = 26 // Miscellaneous: Can User Any Name | |
32 | AccessNoAgreement = 27 // Miscellaneous: Don't Show Agreement | |
33 | AccessSetFileComment = 28 // File System Maintenance: Can Comment Files | |
34 | AccessSetFolderComment = 29 // File System Maintenance: Can Comment Folders | |
35 | AccessViewDropBoxes = 30 // File System Maintenance: Can View Drop Boxes | |
36 | AccessMakeAlias = 31 // File System Maintenance: Can Make Aliases | |
37 | AccessBroadcast = 32 // Messaging: Can Broadcast | |
38 | AccessNewsDeleteArt = 33 // News: Can Delete Articles | |
39 | AccessNewsCreateCat = 34 // News: Can Create Categories | |
40 | AccessNewsDeleteCat = 35 // News: Can Delete Categories | |
41 | AccessNewsCreateFldr = 36 // News: Can Create News Bundles | |
42 | AccessNewsDeleteFldr = 37 // News: Can Delete News Bundles | |
72f8a1fd JH |
43 | AccessUploadFolder = 38 // File System Maintenance: Can Upload Folders |
44 | AccessDownloadFolder = 39 // File System Maintenance: Can Download Folders | |
d9bc63a1 | 45 | AccessSendPrivMsg = 40 // Messaging: Can Send Messages (Note: 1.9 protocol doc incorrectly says this is bit 19) |
6988a057 JH |
46 | ) |
47 | ||
fd740bc4 | 48 | type AccessBitmap [8]byte |
a0241c25 | 49 | |
fd740bc4 | 50 | func (bits *AccessBitmap) Set(i int) { |
a0241c25 JH |
51 | bits[i/8] |= 1 << uint(7-i%8) |
52 | } | |
53 | ||
fd740bc4 | 54 | func (bits *AccessBitmap) IsSet(i int) bool { |
187d6dc5 | 55 | return bits[i/8]&(1<<uint(7-i%8)) != 0 |
6988a057 | 56 | } |
72f8a1fd JH |
57 | |
58 | func (bits *AccessBitmap) UnmarshalYAML(unmarshal func(interface{}) error) error { | |
59 | var flags interface{} | |
60 | err := unmarshal(&flags) | |
61 | if err != nil { | |
62 | return fmt.Errorf("unmarshal access bitmap: %w", err) | |
63 | } | |
64 | ||
65 | switch v := flags.(type) { | |
66 | case []interface{}: | |
67 | // Mobius versions < v0.17.0 store the user access bitmap as an array of int values like: | |
68 | // [96, 112, 12, 32, 3, 128, 0, 0] | |
69 | // This case supports reading of user config files using this format. | |
70 | for i, v := range flags.([]interface{}) { | |
71 | bits[i] = byte(v.(int)) | |
72 | } | |
73 | case map[string]interface{}: | |
74 | // Mobius versions >= v0.17.0 store the user access bitmap as map[string]bool to provide a human-readable view of | |
75 | // the account permissions. | |
76 | if f, ok := v["DeleteFile"].(bool); ok && f { | |
77 | bits.Set(AccessDeleteFile) | |
78 | } | |
79 | if f, ok := v["UploadFile"].(bool); ok && f { | |
80 | bits.Set(AccessUploadFile) | |
81 | } | |
82 | if f, ok := v["DownloadFile"].(bool); ok && f { | |
83 | bits.Set(AccessDownloadFile) | |
84 | } | |
85 | if f, ok := v["UploadFolder"].(bool); ok && f { | |
86 | bits.Set(AccessUploadFolder) | |
87 | } | |
88 | if f, ok := v["DownloadFolder"].(bool); ok && f { | |
89 | bits.Set(AccessDownloadFolder) | |
90 | } | |
91 | if f, ok := v["RenameFile"].(bool); ok && f { | |
92 | bits.Set(AccessRenameFile) | |
93 | } | |
94 | if f, ok := v["MoveFile"].(bool); ok && f { | |
95 | bits.Set(AccessMoveFile) | |
96 | } | |
97 | if f, ok := v["CreateFolder"].(bool); ok && f { | |
98 | bits.Set(AccessCreateFolder) | |
99 | } | |
100 | if f, ok := v["DeleteFolder"].(bool); ok && f { | |
101 | bits.Set(AccessDeleteFolder) | |
102 | } | |
103 | if f, ok := v["RenameFolder"].(bool); ok && f { | |
104 | bits.Set(AccessRenameFolder) | |
105 | } | |
106 | if f, ok := v["MoveFolder"].(bool); ok && f { | |
107 | bits.Set(AccessMoveFolder) | |
108 | } | |
109 | if f, ok := v["ReadChat"].(bool); ok && f { | |
110 | bits.Set(AccessReadChat) | |
111 | } | |
112 | if f, ok := v["SendChat"].(bool); ok && f { | |
113 | bits.Set(AccessSendChat) | |
114 | } | |
115 | if f, ok := v["OpenChat"].(bool); ok && f { | |
116 | bits.Set(AccessOpenChat) | |
117 | } | |
118 | if f, ok := v["CloseChat"].(bool); ok && f { | |
119 | bits.Set(AccessCloseChat) | |
120 | } | |
121 | if f, ok := v["ShowInList"].(bool); ok && f { | |
122 | bits.Set(AccessShowInList) | |
123 | } | |
124 | if f, ok := v["CreateUser"].(bool); ok && f { | |
125 | bits.Set(AccessCreateUser) | |
126 | } | |
127 | if f, ok := v["DeleteUser"].(bool); ok && f { | |
128 | bits.Set(AccessDeleteUser) | |
129 | } | |
130 | if f, ok := v["OpenUser"].(bool); ok && f { | |
131 | bits.Set(AccessOpenUser) | |
132 | } | |
133 | if f, ok := v["ModifyUser"].(bool); ok && f { | |
134 | bits.Set(AccessModifyUser) | |
135 | } | |
136 | if f, ok := v["ChangeOwnPass"].(bool); ok && f { | |
137 | bits.Set(AccessChangeOwnPass) | |
138 | } | |
139 | if f, ok := v["NewsReadArt"].(bool); ok && f { | |
140 | bits.Set(AccessNewsReadArt) | |
141 | } | |
142 | if f, ok := v["NewsPostArt"].(bool); ok && f { | |
143 | bits.Set(AccessNewsPostArt) | |
144 | } | |
145 | if f, ok := v["DisconnectUser"].(bool); ok && f { | |
146 | bits.Set(AccessDisconUser) | |
147 | } | |
148 | if f, ok := v["CannotBeDisconnected"].(bool); ok && f { | |
149 | bits.Set(AccessCannotBeDiscon) | |
150 | } | |
151 | if f, ok := v["GetClientInfo"].(bool); ok && f { | |
152 | bits.Set(AccessGetClientInfo) | |
153 | } | |
154 | if f, ok := v["UploadAnywhere"].(bool); ok && f { | |
155 | bits.Set(AccessUploadAnywhere) | |
156 | } | |
157 | if f, ok := v["AnyName"].(bool); ok && f { | |
158 | bits.Set(AccessAnyName) | |
159 | } | |
160 | if f, ok := v["NoAgreement"].(bool); ok && f { | |
161 | bits.Set(AccessNoAgreement) | |
162 | } | |
163 | if f, ok := v["SetFileComment"].(bool); ok && f { | |
164 | bits.Set(AccessSetFileComment) | |
165 | } | |
166 | if f, ok := v["SetFolderComment"].(bool); ok && f { | |
167 | bits.Set(AccessSetFolderComment) | |
168 | } | |
169 | if f, ok := v["ViewDropBoxes"].(bool); ok && f { | |
170 | bits.Set(AccessViewDropBoxes) | |
171 | } | |
172 | if f, ok := v["MakeAlias"].(bool); ok && f { | |
173 | bits.Set(AccessMakeAlias) | |
174 | } | |
175 | if f, ok := v["Broadcast"].(bool); ok && f { | |
176 | bits.Set(AccessBroadcast) | |
177 | } | |
178 | if f, ok := v["NewsDeleteArt"].(bool); ok && f { | |
179 | bits.Set(AccessNewsDeleteArt) | |
180 | } | |
181 | if f, ok := v["NewsCreateCat"].(bool); ok && f { | |
182 | bits.Set(AccessNewsCreateCat) | |
183 | } | |
184 | if f, ok := v["NewsDeleteCat"].(bool); ok && f { | |
185 | bits.Set(AccessNewsDeleteCat) | |
186 | } | |
187 | if f, ok := v["NewsCreateFldr"].(bool); ok && f { | |
188 | bits.Set(AccessNewsCreateFldr) | |
189 | } | |
190 | if f, ok := v["NewsDeleteFldr"].(bool); ok && f { | |
191 | bits.Set(AccessNewsDeleteFldr) | |
192 | } | |
193 | if f, ok := v["SendPrivMsg"].(bool); ok && f { | |
194 | bits.Set(AccessSendPrivMsg) | |
195 | } | |
196 | } | |
197 | ||
198 | return nil | |
199 | } | |
200 | ||
201 | // accessFlags is used to render the access bitmap to human-readable boolean flags in the account yaml. | |
202 | type accessFlags struct { | |
203 | DownloadFile bool `yaml:"DownloadFile"` | |
204 | DownloadFolder bool `yaml:"DownloadFolder"` | |
205 | UploadFile bool `yaml:"UploadFile"` | |
206 | UploadFolder bool `yaml:"UploadFolder"` | |
207 | DeleteFile bool `yaml:"DeleteFile"` | |
208 | RenameFile bool `yaml:"RenameFile"` | |
209 | MoveFile bool `yaml:"MoveFile"` | |
210 | CreateFolder bool `yaml:"CreateFolder"` | |
211 | DeleteFolder bool `yaml:"DeleteFolder"` | |
212 | RenameFolder bool `yaml:"RenameFolder"` | |
213 | MoveFolder bool `yaml:"MoveFolder"` | |
214 | ReadChat bool `yaml:"ReadChat"` | |
215 | SendChat bool `yaml:"SendChat"` | |
216 | OpenChat bool `yaml:"OpenChat"` | |
217 | CloseChat bool `yaml:"CloseChat"` | |
218 | ShowInList bool `yaml:"ShowInList"` | |
219 | CreateUser bool `yaml:"CreateUser"` | |
220 | DeleteUser bool `yaml:"DeleteUser"` | |
221 | OpenUser bool `yaml:"OpenUser"` | |
222 | ModifyUser bool `yaml:"ModifyUser"` | |
223 | ChangeOwnPass bool `yaml:"ChangeOwnPass"` | |
224 | NewsReadArt bool `yaml:"NewsReadArt"` | |
225 | NewsPostArt bool `yaml:"NewsPostArt"` | |
226 | DisconnectUser bool `yaml:"DisconnectUser"` | |
227 | CannotBeDisconnected bool `yaml:"CannotBeDisconnected"` | |
228 | GetClientInfo bool `yaml:"GetClientInfo"` | |
229 | UploadAnywhere bool `yaml:"UploadAnywhere"` | |
230 | AnyName bool `yaml:"AnyName"` | |
231 | NoAgreement bool `yaml:"NoAgreement"` | |
232 | SetFileComment bool `yaml:"SetFileComment"` | |
233 | SetFolderComment bool `yaml:"SetFolderComment"` | |
234 | ViewDropBoxes bool `yaml:"ViewDropBoxes"` | |
235 | MakeAlias bool `yaml:"MakeAlias"` | |
236 | Broadcast bool `yaml:"Broadcast"` | |
237 | NewsDeleteArt bool `yaml:"NewsDeleteArt"` | |
238 | NewsCreateCat bool `yaml:"NewsCreateCat"` | |
239 | NewsDeleteCat bool `yaml:"NewsDeleteCat"` | |
240 | NewsCreateFldr bool `yaml:"NewsCreateFldr"` | |
241 | NewsDeleteFldr bool `yaml:"NewsDeleteFldr"` | |
242 | SendPrivMsg bool `yaml:"SendPrivMsg"` | |
243 | } | |
244 | ||
245 | func (bits AccessBitmap) MarshalYAML() (interface{}, error) { | |
246 | return accessFlags{ | |
247 | DownloadFile: bits.IsSet(AccessDownloadFile), | |
248 | DownloadFolder: bits.IsSet(AccessDownloadFolder), | |
249 | UploadFolder: bits.IsSet(AccessUploadFolder), | |
250 | DeleteFile: bits.IsSet(AccessDeleteFile), | |
251 | UploadFile: bits.IsSet(AccessUploadFile), | |
252 | RenameFile: bits.IsSet(AccessRenameFile), | |
253 | MoveFile: bits.IsSet(AccessMoveFile), | |
254 | CreateFolder: bits.IsSet(AccessCreateFolder), | |
255 | DeleteFolder: bits.IsSet(AccessDeleteFolder), | |
256 | RenameFolder: bits.IsSet(AccessRenameFolder), | |
257 | MoveFolder: bits.IsSet(AccessMoveFolder), | |
258 | ReadChat: bits.IsSet(AccessReadChat), | |
259 | SendChat: bits.IsSet(AccessSendChat), | |
260 | OpenChat: bits.IsSet(AccessOpenChat), | |
261 | CloseChat: bits.IsSet(AccessCloseChat), | |
262 | ShowInList: bits.IsSet(AccessShowInList), | |
263 | CreateUser: bits.IsSet(AccessCreateUser), | |
264 | DeleteUser: bits.IsSet(AccessDeleteUser), | |
265 | OpenUser: bits.IsSet(AccessOpenUser), | |
266 | ModifyUser: bits.IsSet(AccessModifyUser), | |
267 | ChangeOwnPass: bits.IsSet(AccessChangeOwnPass), | |
268 | NewsReadArt: bits.IsSet(AccessNewsReadArt), | |
269 | NewsPostArt: bits.IsSet(AccessNewsPostArt), | |
270 | DisconnectUser: bits.IsSet(AccessDisconUser), | |
271 | CannotBeDisconnected: bits.IsSet(AccessCannotBeDiscon), | |
272 | GetClientInfo: bits.IsSet(AccessGetClientInfo), | |
273 | UploadAnywhere: bits.IsSet(AccessUploadAnywhere), | |
274 | AnyName: bits.IsSet(AccessAnyName), | |
275 | NoAgreement: bits.IsSet(AccessNoAgreement), | |
276 | SetFileComment: bits.IsSet(AccessSetFileComment), | |
277 | SetFolderComment: bits.IsSet(AccessSetFolderComment), | |
278 | ViewDropBoxes: bits.IsSet(AccessViewDropBoxes), | |
279 | MakeAlias: bits.IsSet(AccessMakeAlias), | |
280 | Broadcast: bits.IsSet(AccessBroadcast), | |
281 | NewsDeleteArt: bits.IsSet(AccessNewsDeleteArt), | |
282 | NewsCreateCat: bits.IsSet(AccessNewsCreateCat), | |
283 | NewsDeleteCat: bits.IsSet(AccessNewsDeleteCat), | |
284 | NewsCreateFldr: bits.IsSet(AccessNewsCreateFldr), | |
285 | NewsDeleteFldr: bits.IsSet(AccessNewsDeleteFldr), | |
286 | SendPrivMsg: bits.IsSet(AccessSendPrivMsg), | |
287 | }, nil | |
288 | } |