imapkit 4.3.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -51
- package/bin/help.txt +17 -3
- package/bin/imapkit.js +53 -23
- package/dist/cjs/commands/append.js +1 -1
- package/dist/cjs/commands/create.js +2 -2
- package/dist/cjs/commands/delete.js +2 -14
- package/dist/cjs/commands/handlers/flags.d.ts +3 -3
- package/dist/cjs/commands/handlers/flags.js +3 -3
- package/dist/cjs/commands/handlers/store.js +3 -3
- package/dist/cjs/commands/rename.js +6 -46
- package/dist/cjs/commands/select.js +1 -0
- package/dist/cjs/commands/subscribe.js +7 -8
- package/dist/cjs/commands/unsubscribe.js +3 -9
- package/dist/cjs/control.d.ts +430 -0
- package/dist/cjs/control.js +637 -0
- package/dist/cjs/index.d.ts +8 -1
- package/dist/cjs/index.js +9 -2
- package/dist/cjs/load-plugins.d.ts +1 -1
- package/dist/cjs/load-plugins.js +7 -2
- package/dist/cjs/plugins/acl.js +109 -42
- package/dist/cjs/plugins/condstore.js +7 -0
- package/dist/cjs/plugins/index.js +1 -3
- package/dist/cjs/plugins/metadata.js +140 -57
- package/dist/cjs/plugins/objectid.js +10 -0
- package/dist/cjs/plugins/quota.js +50 -2
- package/dist/cjs/plugins/savedate.js +1 -1
- package/dist/cjs/plugins/special-use.d.ts +0 -8
- package/dist/cjs/plugins/special-use.js +23 -0
- package/dist/cjs/quirks.d.ts +28 -0
- package/dist/cjs/quirks.js +124 -0
- package/dist/cjs/random.d.ts +10 -0
- package/dist/cjs/random.js +22 -0
- package/dist/cjs/rest.d.ts +50 -0
- package/dist/cjs/rest.js +561 -0
- package/dist/cjs/script.d.ts +33 -4
- package/dist/cjs/script.js +64 -4
- package/dist/cjs/server.d.ts +149 -8
- package/dist/cjs/server.js +429 -152
- package/dist/cjs/smtp-listener.d.ts +3 -2
- package/dist/cjs/smtp-listener.js +10 -6
- package/dist/cjs/storage-schema.d.ts +139 -0
- package/dist/cjs/storage-schema.js +215 -0
- package/dist/cjs/store-operations.d.ts +168 -0
- package/dist/cjs/store-operations.js +422 -0
- package/dist/cjs/types.d.ts +22 -1
- package/dist/esm/commands/append.js +1 -1
- package/dist/esm/commands/create.js +2 -2
- package/dist/esm/commands/delete.js +2 -14
- package/dist/esm/commands/handlers/flags.d.ts +3 -3
- package/dist/esm/commands/handlers/flags.js +3 -3
- package/dist/esm/commands/handlers/store.js +3 -3
- package/dist/esm/commands/rename.js +6 -46
- package/dist/esm/commands/select.js +1 -0
- package/dist/esm/commands/subscribe.js +7 -8
- package/dist/esm/commands/unsubscribe.js +3 -9
- package/dist/esm/control.d.ts +430 -0
- package/dist/esm/control.js +630 -0
- package/dist/esm/index.d.ts +8 -1
- package/dist/esm/index.js +5 -2
- package/dist/esm/load-plugins.d.ts +1 -1
- package/dist/esm/load-plugins.js +7 -2
- package/dist/esm/plugins/acl.js +109 -42
- package/dist/esm/plugins/condstore.js +7 -0
- package/dist/esm/plugins/index.js +1 -3
- package/dist/esm/plugins/metadata.js +140 -57
- package/dist/esm/plugins/objectid.js +10 -0
- package/dist/esm/plugins/quota.js +50 -2
- package/dist/esm/plugins/savedate.js +1 -1
- package/dist/esm/plugins/special-use.d.ts +0 -8
- package/dist/esm/plugins/special-use.js +23 -0
- package/dist/esm/quirks.d.ts +28 -0
- package/dist/esm/quirks.js +120 -0
- package/dist/esm/random.d.ts +10 -0
- package/dist/esm/random.js +19 -0
- package/dist/esm/rest.d.ts +50 -0
- package/dist/esm/rest.js +553 -0
- package/dist/esm/script.d.ts +33 -4
- package/dist/esm/script.js +63 -4
- package/dist/esm/server.d.ts +149 -8
- package/dist/esm/server.js +429 -152
- package/dist/esm/smtp-listener.d.ts +3 -2
- package/dist/esm/smtp-listener.js +10 -6
- package/dist/esm/storage-schema.d.ts +139 -0
- package/dist/esm/storage-schema.js +211 -0
- package/dist/esm/store-operations.d.ts +168 -0
- package/dist/esm/store-operations.js +407 -0
- package/dist/esm/types.d.ts +22 -1
- package/dist/plugin-help.json +0 -14
- package/package.json +11 -3
- package/dist/cjs/plugins/xtoybird.d.ts +0 -2
- package/dist/cjs/plugins/xtoybird.js +0 -236
- package/dist/esm/plugins/xtoybird.d.ts +0 -2
- package/dist/esm/plugins/xtoybird.js +0 -218
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.default = xtoybirdPlugin;
|
|
7
|
-
const command_states_js_1 = require("../command-states.js");
|
|
8
|
-
/**
|
|
9
|
-
* @help Custom plugin to allow programmatic control of the server
|
|
10
|
-
* @help Available commands:
|
|
11
|
-
* @help XTOYBIRD SERVER dumps server internals
|
|
12
|
-
* @help XTOYBIRD CONNECTION dumps connection internals
|
|
13
|
-
* @help XTOYBIRD STORAGE dumps storage as JSON
|
|
14
|
-
* @help XTOYBIRD USERADD "username" "password" adds or updates user
|
|
15
|
-
* @help XTOYBIRD USERDEL "username" removes a user
|
|
16
|
-
* @help XTOYBIRD SHUTDOWN Closes the server after the last client
|
|
17
|
-
* @help disconnects. New connections are rejected.
|
|
18
|
-
* @help Commands are only allowed after login, and only for the owner
|
|
19
|
-
* @help (aclOwner option) when ACL is loaded. A test control plugin,
|
|
20
|
-
* @help any user it allows can read and change everything
|
|
21
|
-
*/
|
|
22
|
-
const node_util_1 = __importDefault(require("node:util"));
|
|
23
|
-
const arguments_js_1 = require("../arguments.js");
|
|
24
|
-
function xtoybirdPlugin(server) {
|
|
25
|
-
let username;
|
|
26
|
-
let password;
|
|
27
|
-
let message;
|
|
28
|
-
const sendError = (connection, parsed, data, callback, command, message) => {
|
|
29
|
-
connection.sendStatus(parsed, data, command, message, false, 'INVALID COMMAND');
|
|
30
|
-
return callback();
|
|
31
|
-
};
|
|
32
|
-
server.setCommandHandler('XTOYBIRD', (connection, parsed, data, callback) => {
|
|
33
|
-
// XTOYBIRD bypasses every access check (STORAGE dumps all mailboxes), so with ACL only the owner may use it
|
|
34
|
-
if (server.acl && !server.acl.isOwner(connection)) {
|
|
35
|
-
connection.sendStatus(parsed, data, 'NO', 'XTOYBIRD is only allowed for the owner', 'NOPERM', 'INVALID COMMAND');
|
|
36
|
-
return callback();
|
|
37
|
-
}
|
|
38
|
-
if (parsed.attributes) {
|
|
39
|
-
const subcommand = ((parsed.attributes[0] && parsed.attributes[0].value) || '').toString().toUpperCase();
|
|
40
|
-
if (subcommand === 'USERADD' && (parsed.attributes.length !== 3 || !(0, arguments_js_1.isAstring)(parsed.attributes[1]) || !(0, arguments_js_1.isAstring)(parsed.attributes[2]))) {
|
|
41
|
-
return sendError(connection, parsed, data, callback, 'BAD', 'USERADD expects username and password');
|
|
42
|
-
}
|
|
43
|
-
if (subcommand === 'USERDEL' && (parsed.attributes.length !== 2 || !(0, arguments_js_1.isAstring)(parsed.attributes[1]))) {
|
|
44
|
-
return sendError(connection, parsed, data, callback, 'BAD', 'USERDEL expects username');
|
|
45
|
-
}
|
|
46
|
-
switch (subcommand) {
|
|
47
|
-
case 'SERVER':
|
|
48
|
-
connection.send({
|
|
49
|
-
tag: '*',
|
|
50
|
-
command: 'XTOYBIRD',
|
|
51
|
-
attributes: [
|
|
52
|
-
{
|
|
53
|
-
type: 'SECTION',
|
|
54
|
-
section: [
|
|
55
|
-
{
|
|
56
|
-
type: 'ATOM',
|
|
57
|
-
value: 'XDUMPVAL'
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
type: 'LITERAL',
|
|
63
|
-
value: node_util_1.default.inspect(server, false, 22)
|
|
64
|
-
}
|
|
65
|
-
]
|
|
66
|
-
}, 'CONNECTION STATUS', parsed, data);
|
|
67
|
-
break;
|
|
68
|
-
case 'CONNECTION':
|
|
69
|
-
connection.send({
|
|
70
|
-
tag: '*',
|
|
71
|
-
command: 'XTOYBIRD',
|
|
72
|
-
attributes: [
|
|
73
|
-
{
|
|
74
|
-
type: 'SECTION',
|
|
75
|
-
section: [
|
|
76
|
-
{
|
|
77
|
-
type: 'ATOM',
|
|
78
|
-
value: 'XDUMPVAL'
|
|
79
|
-
}
|
|
80
|
-
]
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
type: 'LITERAL',
|
|
84
|
-
value: node_util_1.default.inspect(connection, false, 22)
|
|
85
|
-
}
|
|
86
|
-
]
|
|
87
|
-
}, 'CONNECTION STATUS', parsed, data);
|
|
88
|
-
break;
|
|
89
|
-
case 'STORAGE':
|
|
90
|
-
connection.send({
|
|
91
|
-
tag: '*',
|
|
92
|
-
command: 'XTOYBIRD',
|
|
93
|
-
attributes: [
|
|
94
|
-
{
|
|
95
|
-
type: 'SECTION',
|
|
96
|
-
section: [
|
|
97
|
-
{
|
|
98
|
-
type: 'ATOM',
|
|
99
|
-
value: 'XJSONDUMP'
|
|
100
|
-
}
|
|
101
|
-
]
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
type: 'LITERAL',
|
|
105
|
-
value: JSON.stringify(connection.server.storage, null, 4)
|
|
106
|
-
}
|
|
107
|
-
]
|
|
108
|
-
}, 'CONNECTION STATUS', parsed, data);
|
|
109
|
-
break;
|
|
110
|
-
case 'USERADD':
|
|
111
|
-
username = parsed.attributes[1].value || '';
|
|
112
|
-
password = parsed.attributes[2].value || '';
|
|
113
|
-
if (connection.server.getUser(username)) {
|
|
114
|
-
connection.server.users[username].password = password;
|
|
115
|
-
message = 'updated';
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
connection.server.users[username] = {
|
|
119
|
-
password: password
|
|
120
|
-
};
|
|
121
|
-
message = 'added';
|
|
122
|
-
}
|
|
123
|
-
connection.send({
|
|
124
|
-
tag: '*',
|
|
125
|
-
command: 'XTOYBIRD',
|
|
126
|
-
attributes: [
|
|
127
|
-
{
|
|
128
|
-
type: 'SECTION',
|
|
129
|
-
section: [
|
|
130
|
-
{
|
|
131
|
-
type: 'ATOM',
|
|
132
|
-
value: 'XUSER'
|
|
133
|
-
}
|
|
134
|
-
]
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
type: 'TEXT',
|
|
138
|
-
value: 'User ' + displayName(username) + message + ' successfully'
|
|
139
|
-
}
|
|
140
|
-
]
|
|
141
|
-
}, 'CONNECTION USERADD', parsed, data);
|
|
142
|
-
break;
|
|
143
|
-
case 'USERDEL':
|
|
144
|
-
username = parsed.attributes[1].value || '';
|
|
145
|
-
if (username in connection.server.users) {
|
|
146
|
-
delete connection.server.users[username];
|
|
147
|
-
message = 'succeeded';
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
message = 'failed (no such user)';
|
|
151
|
-
}
|
|
152
|
-
connection.send({
|
|
153
|
-
tag: '*',
|
|
154
|
-
command: 'XTOYBIRD',
|
|
155
|
-
attributes: [
|
|
156
|
-
{
|
|
157
|
-
type: 'SECTION',
|
|
158
|
-
section: [
|
|
159
|
-
{
|
|
160
|
-
type: 'ATOM',
|
|
161
|
-
value: 'XUSER'
|
|
162
|
-
}
|
|
163
|
-
]
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
type: 'TEXT',
|
|
167
|
-
value: 'Removing user ' + displayName(username) + message
|
|
168
|
-
}
|
|
169
|
-
]
|
|
170
|
-
}, 'CONNECTION USERDEL', parsed, data);
|
|
171
|
-
break;
|
|
172
|
-
case 'SHUTDOWN':
|
|
173
|
-
connection.send({
|
|
174
|
-
tag: '*',
|
|
175
|
-
command: 'OK',
|
|
176
|
-
attributes: [
|
|
177
|
-
{
|
|
178
|
-
type: 'SECTION',
|
|
179
|
-
section: [
|
|
180
|
-
{
|
|
181
|
-
type: 'ATOM',
|
|
182
|
-
value: 'ALERT'
|
|
183
|
-
}
|
|
184
|
-
]
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
type: 'TEXT',
|
|
188
|
-
value: 'System scheduled for shutdown'
|
|
189
|
-
}
|
|
190
|
-
]
|
|
191
|
-
}, 'CONNECTION SHUTDOWN', parsed, data);
|
|
192
|
-
connection.server.close();
|
|
193
|
-
break;
|
|
194
|
-
default:
|
|
195
|
-
connection.send({
|
|
196
|
-
tag: parsed.tag,
|
|
197
|
-
command: 'BAD',
|
|
198
|
-
attributes: [
|
|
199
|
-
{
|
|
200
|
-
type: 'TEXT',
|
|
201
|
-
value: 'Unknown command'
|
|
202
|
-
}
|
|
203
|
-
]
|
|
204
|
-
}, 'INVALID COMMAND', parsed, data);
|
|
205
|
-
return callback();
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
connection.send({
|
|
209
|
-
tag: parsed.tag,
|
|
210
|
-
command: 'OK',
|
|
211
|
-
attributes: [
|
|
212
|
-
{
|
|
213
|
-
type: 'TEXT',
|
|
214
|
-
value: 'XTOYBIRD Completed'
|
|
215
|
-
}
|
|
216
|
-
]
|
|
217
|
-
}, 'XTOYBIRD', parsed, data);
|
|
218
|
-
return callback();
|
|
219
|
-
}, { states: command_states_js_1.states.AUTHENTICATED });
|
|
220
|
-
}
|
|
221
|
-
// Response text is free text that some clients still tokenize, so only plain user names are echoed
|
|
222
|
-
function displayName(username) {
|
|
223
|
-
return /^[\w.@+-]+$/.test(username) ? "'" + username + "' " : '';
|
|
224
|
-
}
|
|
225
|
-
{
|
|
226
|
-
const defaultExport = exports.default;
|
|
227
|
-
if (defaultExport && (typeof defaultExport === 'function' || typeof defaultExport === 'object')) {
|
|
228
|
-
for (const key of Object.keys(exports)) {
|
|
229
|
-
if (key !== 'default' && !(key in defaultExport)) {
|
|
230
|
-
defaultExport[key] = exports[key];
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
Object.defineProperty(defaultExport, 'default', { value: defaultExport, enumerable: false, writable: true, configurable: true });
|
|
234
|
-
module.exports = defaultExport;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import { states } from '../command-states.js';
|
|
2
|
-
/**
|
|
3
|
-
* @help Custom plugin to allow programmatic control of the server
|
|
4
|
-
* @help Available commands:
|
|
5
|
-
* @help XTOYBIRD SERVER dumps server internals
|
|
6
|
-
* @help XTOYBIRD CONNECTION dumps connection internals
|
|
7
|
-
* @help XTOYBIRD STORAGE dumps storage as JSON
|
|
8
|
-
* @help XTOYBIRD USERADD "username" "password" adds or updates user
|
|
9
|
-
* @help XTOYBIRD USERDEL "username" removes a user
|
|
10
|
-
* @help XTOYBIRD SHUTDOWN Closes the server after the last client
|
|
11
|
-
* @help disconnects. New connections are rejected.
|
|
12
|
-
* @help Commands are only allowed after login, and only for the owner
|
|
13
|
-
* @help (aclOwner option) when ACL is loaded. A test control plugin,
|
|
14
|
-
* @help any user it allows can read and change everything
|
|
15
|
-
*/
|
|
16
|
-
import util from 'node:util';
|
|
17
|
-
import { isAstring } from '../arguments.js';
|
|
18
|
-
export default function xtoybirdPlugin(server) {
|
|
19
|
-
let username;
|
|
20
|
-
let password;
|
|
21
|
-
let message;
|
|
22
|
-
const sendError = (connection, parsed, data, callback, command, message) => {
|
|
23
|
-
connection.sendStatus(parsed, data, command, message, false, 'INVALID COMMAND');
|
|
24
|
-
return callback();
|
|
25
|
-
};
|
|
26
|
-
server.setCommandHandler('XTOYBIRD', (connection, parsed, data, callback) => {
|
|
27
|
-
// XTOYBIRD bypasses every access check (STORAGE dumps all mailboxes), so with ACL only the owner may use it
|
|
28
|
-
if (server.acl && !server.acl.isOwner(connection)) {
|
|
29
|
-
connection.sendStatus(parsed, data, 'NO', 'XTOYBIRD is only allowed for the owner', 'NOPERM', 'INVALID COMMAND');
|
|
30
|
-
return callback();
|
|
31
|
-
}
|
|
32
|
-
if (parsed.attributes) {
|
|
33
|
-
const subcommand = ((parsed.attributes[0] && parsed.attributes[0].value) || '').toString().toUpperCase();
|
|
34
|
-
if (subcommand === 'USERADD' && (parsed.attributes.length !== 3 || !isAstring(parsed.attributes[1]) || !isAstring(parsed.attributes[2]))) {
|
|
35
|
-
return sendError(connection, parsed, data, callback, 'BAD', 'USERADD expects username and password');
|
|
36
|
-
}
|
|
37
|
-
if (subcommand === 'USERDEL' && (parsed.attributes.length !== 2 || !isAstring(parsed.attributes[1]))) {
|
|
38
|
-
return sendError(connection, parsed, data, callback, 'BAD', 'USERDEL expects username');
|
|
39
|
-
}
|
|
40
|
-
switch (subcommand) {
|
|
41
|
-
case 'SERVER':
|
|
42
|
-
connection.send({
|
|
43
|
-
tag: '*',
|
|
44
|
-
command: 'XTOYBIRD',
|
|
45
|
-
attributes: [
|
|
46
|
-
{
|
|
47
|
-
type: 'SECTION',
|
|
48
|
-
section: [
|
|
49
|
-
{
|
|
50
|
-
type: 'ATOM',
|
|
51
|
-
value: 'XDUMPVAL'
|
|
52
|
-
}
|
|
53
|
-
]
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
type: 'LITERAL',
|
|
57
|
-
value: util.inspect(server, false, 22)
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
}, 'CONNECTION STATUS', parsed, data);
|
|
61
|
-
break;
|
|
62
|
-
case 'CONNECTION':
|
|
63
|
-
connection.send({
|
|
64
|
-
tag: '*',
|
|
65
|
-
command: 'XTOYBIRD',
|
|
66
|
-
attributes: [
|
|
67
|
-
{
|
|
68
|
-
type: 'SECTION',
|
|
69
|
-
section: [
|
|
70
|
-
{
|
|
71
|
-
type: 'ATOM',
|
|
72
|
-
value: 'XDUMPVAL'
|
|
73
|
-
}
|
|
74
|
-
]
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
type: 'LITERAL',
|
|
78
|
-
value: util.inspect(connection, false, 22)
|
|
79
|
-
}
|
|
80
|
-
]
|
|
81
|
-
}, 'CONNECTION STATUS', parsed, data);
|
|
82
|
-
break;
|
|
83
|
-
case 'STORAGE':
|
|
84
|
-
connection.send({
|
|
85
|
-
tag: '*',
|
|
86
|
-
command: 'XTOYBIRD',
|
|
87
|
-
attributes: [
|
|
88
|
-
{
|
|
89
|
-
type: 'SECTION',
|
|
90
|
-
section: [
|
|
91
|
-
{
|
|
92
|
-
type: 'ATOM',
|
|
93
|
-
value: 'XJSONDUMP'
|
|
94
|
-
}
|
|
95
|
-
]
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
type: 'LITERAL',
|
|
99
|
-
value: JSON.stringify(connection.server.storage, null, 4)
|
|
100
|
-
}
|
|
101
|
-
]
|
|
102
|
-
}, 'CONNECTION STATUS', parsed, data);
|
|
103
|
-
break;
|
|
104
|
-
case 'USERADD':
|
|
105
|
-
username = parsed.attributes[1].value || '';
|
|
106
|
-
password = parsed.attributes[2].value || '';
|
|
107
|
-
if (connection.server.getUser(username)) {
|
|
108
|
-
connection.server.users[username].password = password;
|
|
109
|
-
message = 'updated';
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
connection.server.users[username] = {
|
|
113
|
-
password: password
|
|
114
|
-
};
|
|
115
|
-
message = 'added';
|
|
116
|
-
}
|
|
117
|
-
connection.send({
|
|
118
|
-
tag: '*',
|
|
119
|
-
command: 'XTOYBIRD',
|
|
120
|
-
attributes: [
|
|
121
|
-
{
|
|
122
|
-
type: 'SECTION',
|
|
123
|
-
section: [
|
|
124
|
-
{
|
|
125
|
-
type: 'ATOM',
|
|
126
|
-
value: 'XUSER'
|
|
127
|
-
}
|
|
128
|
-
]
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
type: 'TEXT',
|
|
132
|
-
value: 'User ' + displayName(username) + message + ' successfully'
|
|
133
|
-
}
|
|
134
|
-
]
|
|
135
|
-
}, 'CONNECTION USERADD', parsed, data);
|
|
136
|
-
break;
|
|
137
|
-
case 'USERDEL':
|
|
138
|
-
username = parsed.attributes[1].value || '';
|
|
139
|
-
if (username in connection.server.users) {
|
|
140
|
-
delete connection.server.users[username];
|
|
141
|
-
message = 'succeeded';
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
message = 'failed (no such user)';
|
|
145
|
-
}
|
|
146
|
-
connection.send({
|
|
147
|
-
tag: '*',
|
|
148
|
-
command: 'XTOYBIRD',
|
|
149
|
-
attributes: [
|
|
150
|
-
{
|
|
151
|
-
type: 'SECTION',
|
|
152
|
-
section: [
|
|
153
|
-
{
|
|
154
|
-
type: 'ATOM',
|
|
155
|
-
value: 'XUSER'
|
|
156
|
-
}
|
|
157
|
-
]
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
type: 'TEXT',
|
|
161
|
-
value: 'Removing user ' + displayName(username) + message
|
|
162
|
-
}
|
|
163
|
-
]
|
|
164
|
-
}, 'CONNECTION USERDEL', parsed, data);
|
|
165
|
-
break;
|
|
166
|
-
case 'SHUTDOWN':
|
|
167
|
-
connection.send({
|
|
168
|
-
tag: '*',
|
|
169
|
-
command: 'OK',
|
|
170
|
-
attributes: [
|
|
171
|
-
{
|
|
172
|
-
type: 'SECTION',
|
|
173
|
-
section: [
|
|
174
|
-
{
|
|
175
|
-
type: 'ATOM',
|
|
176
|
-
value: 'ALERT'
|
|
177
|
-
}
|
|
178
|
-
]
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
type: 'TEXT',
|
|
182
|
-
value: 'System scheduled for shutdown'
|
|
183
|
-
}
|
|
184
|
-
]
|
|
185
|
-
}, 'CONNECTION SHUTDOWN', parsed, data);
|
|
186
|
-
connection.server.close();
|
|
187
|
-
break;
|
|
188
|
-
default:
|
|
189
|
-
connection.send({
|
|
190
|
-
tag: parsed.tag,
|
|
191
|
-
command: 'BAD',
|
|
192
|
-
attributes: [
|
|
193
|
-
{
|
|
194
|
-
type: 'TEXT',
|
|
195
|
-
value: 'Unknown command'
|
|
196
|
-
}
|
|
197
|
-
]
|
|
198
|
-
}, 'INVALID COMMAND', parsed, data);
|
|
199
|
-
return callback();
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
connection.send({
|
|
203
|
-
tag: parsed.tag,
|
|
204
|
-
command: 'OK',
|
|
205
|
-
attributes: [
|
|
206
|
-
{
|
|
207
|
-
type: 'TEXT',
|
|
208
|
-
value: 'XTOYBIRD Completed'
|
|
209
|
-
}
|
|
210
|
-
]
|
|
211
|
-
}, 'XTOYBIRD', parsed, data);
|
|
212
|
-
return callback();
|
|
213
|
-
}, { states: states.AUTHENTICATED });
|
|
214
|
-
}
|
|
215
|
-
// Response text is free text that some clients still tokenize, so only plain user names are echoed
|
|
216
|
-
function displayName(username) {
|
|
217
|
-
return /^[\w.@+-]+$/.test(username) ? "'" + username + "' " : '';
|
|
218
|
-
}
|