Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
Synchronet
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Main
Synchronet
Commits
f6162ed9
Commit
f6162ed9
authored
15 years ago
by
deuce
Browse files
Options
Downloads
Patches
Plain Diff
Better command parser, add handlers for all commands/states.
parent
8713da12
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
exec/imapservice.js
+317
-58
317 additions, 58 deletions
exec/imapservice.js
with
317 additions
and
58 deletions
exec/imapservice.js
+
317
−
58
View file @
f6162ed9
...
@@ -32,74 +32,202 @@ function untagged(msg)
...
@@ -32,74 +32,202 @@ function untagged(msg)
debug_log
(
"
IMAP Send: *
"
+
msg
);
debug_log
(
"
IMAP Send: *
"
+
msg
);
}
}
function
parse_line
(
line
)
{
function
handle_command
(
command
,
args
,
defs
)
var
args
=
[];
{
var
tmp
;
if
(
defs
[
command
]
!=
undefined
)
{
var
tmp2
;
if
(
defs
[
command
].
arguments
!=
undefined
)
{
var
i
;
if
(
args
.
length
-
1
==
defs
[
command
].
arguments
)
{
defs
[
command
].
handler
(
args
);
tmp
=
line
.
split
(
/ /
);
return
(
true
);
while
(
tmp
.
length
)
{
if
(
tmp
[
0
].
substr
(
0
,
1
)
==
'
"
'
)
{
tmp2
=
''
;
while
(
tmp
[
0
].
substr
(
-
1
)
!=
'
"
'
)
{
tmp2
+=
tmp
.
shift
()
+
"
"
;
}
}
tmp2
+=
tmp
.
shift
();
tmp2
=
tmp2
.
replace
(
/^"
(
.*
)
"$/
,
"
$1
"
);
args
.
push
(
tmp2
);
continue
;
}
}
if
(
tmp
[
0
].
substr
(
0
,
1
)
==
'
(
'
)
{
else
if
(
defs
[
command
].
arguments_valid
(
args
.
length
-
1
))
{
tmp2
=
[];
defs
[
command
].
handler
(
args
);
while
(
tmp
[
0
].
substr
(
-
1
)
!=
'
)
'
)
{
return
(
true
);
tmp2
+=
tmp
.
shift
();
}
}
return
false
;
}
function
compNumbers
(
a
,
b
)
{
return
(
a
-
b
);
}
/*
* Parses a data items FETCH parameter for send_fetch_response()
*/
function
parse_data_items
(
obj
)
{
if
(
typeof
(
obj
)
==
'
string
'
)
{
switch
(
obj
.
toUpperCase
())
{
case
'
ALL
'
:
obj
=
[
"
FLAGS
"
,
"
INTERNALDATE
"
,
"
RFC822.SIZE
"
,
"
ENVELOPE
"
];
break
;
case
'
FAST
'
:
obj
=
[
"
FLAGS
"
,
"
INTERNALDATE
"
,
"
RFC822.SIZE
"
];
break
;
case
'
FULL
'
:
obj
=
[
"
FLAGS
"
,
"
INTERNALDATE
"
,
"
RFC822.SIZE
"
,
"
ENVELOPE
"
,
"
BODY
"
];
break
;
default
:
obj
=
[];
}
}
}
/*
* Returns an array of Message Numbers which correspond to the specified sets
*/
function
parse_seq_set
(
set
,
uid
)
{
var
response
=
[];
var
chunks
=
set
.
split
(
/,/
);
var
chunk
;
var
range
;
var
i
;
var
max
;
var
idx
;
if
(
uid
)
max
=
base
.
last_msg
;
else
max
=
base
.
total_msgs
;
for
(
chunk
in
chunks
)
{
range
=
chunks
[
chunk
].
split
(
/:/
);
if
(
range
.
length
==
1
)
range
.
push
(
range
[
0
]);
if
(
range
[
0
]
==
'
*
'
)
range
[
0
]
=
max
;
if
(
range
[
1
]
==
'
*
'
)
range
[
1
]
=
max
;
range
[
0
]
=
parseInt
(
range
[
0
],
10
);
range
[
1
]
=
parseInt
(
range
[
1
],
10
);
if
(
range
[
0
]
>
range
[
1
])
{
i
=
range
[
0
];
range
[
0
]
=
range
[
1
];
range
[
1
]
=
i
;
}
for
(
i
=
range
[
0
];
i
<=
range
[
1
];
i
++
)
{
idx
=
base
.
get_msg_index
(
uid
?
false
:
true
,
parseInt
(
i
,
10
));
if
(
idx
!=
null
)
{
response
.
push
(
idx
.
number
);
}
}
tmp2
+=
tmp
.
shift
();
tmp2
=
tmp2
.
replace
(
/^"
(
.*
)
"$/
,
"
$1
"
);
args
.
push
(
tmp2
);
continue
;
}
}
if
(
tmp
[
0
].
search
(
/^{
[
0-9
]
+}$/
)
!=
-
1
)
{
}
tmp2
=
tmp
[
0
].
replace
(
/^{
([
0-9
]
+
)
}$/
,
"
$1
"
);
response
=
response
.
sort
(
compNumbers
);
args
.
push
(
client
.
socket
.
recv
(
parseInt
(
tmp2
)));
for
(
i
=
0
;
i
<
response
.
length
;
i
++
)
{
tmp2
=
client
.
socket
.
recvline
(
1024
,
300
);
if
(
response
[
i
]
==
response
[
i
+
1
])
{
tmp
=
tmp2
.
split
(
/ /
);
response
.
splice
(
i
+
1
,
1
);
continue
;
i
--
;
}
}
return
(
response
);
}
var
line
;
function
parse_line
()
{
var
at_start
=
true
;
var
in_quote
=
false
;
var
paren_depth
=
0
;
var
string_len
;
var
args
=
[];
var
pos
;
function
parse_atom
()
{
var
ret
=
''
;
while
(
line
.
length
)
{
switch
(
line
.
charAt
(
0
))
{
case
'
)
'
:
return
(
ret
);
case
'
'
:
line
=
line
.
substr
(
1
);
return
(
ret
);
default
:
ret
+=
line
.
charAt
(
0
);
line
=
line
.
substr
(
1
);
break
;
}
}
}
args
.
push
(
tmp
.
shift
()
);
return
(
ret
);
}
}
if
(
args
.
length
<
2
)
{
function
parse_string
()
tagged
(
args
[
0
],
"
BAD
"
,
"
Bad dog, no cookie.
"
);
{
return
;
var
ret
=
''
;
line
=
line
.
replace
(
/^{
([
0-9
]
+
)
}$/
,
"
$1
"
);
client
.
socket
.
send
(
"
+
\r\n
"
);
ret
=
client
.
socket
.
recv
(
parseInt
(
line
));
line
=
client
.
socket
.
recvline
(
1024
,
300
);
return
(
ret
);
}
}
command
=
args
[
1
].
toUpperCase
();
args
.
splice
(
1
,
1
);
function
parse_quotedstring
()
{
if
(
any_state_command_handlers
[
command
]
!=
undefined
)
{
var
ret
=
''
;
if
(
args
.
length
-
1
==
any_state_command_handlers
[
command
].
arguments
)
{
any_state_command_handlers
[
command
].
handler
(
args
);
line
=
line
.
substr
(
1
);
// Remove leading "
return
;
while
(
line
.
length
)
{
switch
(
line
.
charAt
(
0
))
{
case
'
"
'
:
line
=
line
.
substr
(
1
);
return
(
ret
);
default
:
ret
+=
line
.
charAt
(
0
);
line
=
line
.
substr
(
1
);
break
;
}
}
}
return
(
ret
);
}
}
switch
(
state
)
{
case
UnAuthenticated
:
while
(
line
.
length
)
{
if
(
unauthenticated_command_handlers
[
command
]
!=
undefined
)
{
switch
(
line
.
charAt
(
0
))
{
if
(
args
.
length
-
1
==
unauthenticated_command_handlers
[
command
].
arguments
)
{
case
'
"
'
:
unauthenticated_command_handlers
[
command
].
handler
(
args
);
args
.
push
(
parse_quotedstring
());
break
;
case
'
)
'
:
line
=
line
.
substr
(
1
);
return
(
args
);
case
'
(
'
:
line
=
line
.
substr
(
1
);
args
.
push
(
parse_line
());
break
;
case
'
{
'
:
args
.
push
(
parse_string
());
break
;
case
'
'
:
line
=
line
.
substr
(
1
);
break
;
default
:
args
.
push
(
parse_atom
());
break
;
}
}
return
(
args
);
}
function
execute_line
(
args
)
{
if
(
args
.
length
>=
2
)
{
command
=
args
[
1
].
toUpperCase
();
args
.
splice
(
1
,
1
);
if
(
handle_command
(
command
,
args
,
any_state_command_handlers
))
return
;
switch
(
state
)
{
case
UnAuthenticated
:
if
(
handle_command
(
command
,
args
,
unauthenticated_command_handlers
))
return
;
return
;
}
break
;
}
case
Authenticated
:
break
;
if
(
handle_command
(
command
,
args
,
authenticated_command_handlers
))
case
Authenticated
:
if
(
authenticated_command_handlers
[
command
]
!=
undefined
)
{
if
(
args
.
length
-
1
==
authenticated_command_handlers
[
command
].
arguments
)
{
authenticated_command_handlers
[
command
].
handler
(
args
);
return
;
return
;
}
break
;
}
case
Selected
:
break
;
if
(
handle_command
(
command
,
args
,
selected_command_handlers
))
return
;
break
;
}
}
}
tagged
(
args
[
0
],
"
BAD
"
,
"
Bad dog, no cookie.
"
);
tagged
(
args
[
0
],
"
BAD
"
,
"
Bad dog, no cookie.
"
);
}
}
...
@@ -107,6 +235,7 @@ function parse_line(line) {
...
@@ -107,6 +235,7 @@ function parse_line(line) {
// Global variables
// Global variables
const
UnAuthenticated
=
0
;
const
UnAuthenticated
=
0
;
const
Authenticated
=
1
;
const
Authenticated
=
1
;
const
Selected
=
2
;
var
state
=
UnAuthenticated
;
var
state
=
UnAuthenticated
;
var
base
;
var
base
;
...
@@ -271,6 +400,7 @@ authenticated_command_handlers = {
...
@@ -271,6 +400,7 @@ authenticated_command_handlers = {
untagged
(
"
OK [UIDNEXT
"
+
(
base
.
last_msg
+
1
)
+
"
]
"
);
untagged
(
"
OK [UIDNEXT
"
+
(
base
.
last_msg
+
1
)
+
"
]
"
);
untagged
(
"
OK [UIDVALIDITY 0]
"
);
untagged
(
"
OK [UIDVALIDITY 0]
"
);
tagged
(
tag
,
"
OK
"
,
"
[READ-ONLY] Mailbox
"
+
sub
+
"
has been selected
"
);
tagged
(
tag
,
"
OK
"
,
"
[READ-ONLY] Mailbox
"
+
sub
+
"
has been selected
"
);
state
=
Selected
;
},
},
},
},
EXAMINE
:{
// Same as select onlt without the writability
EXAMINE
:{
// Same as select onlt without the writability
...
@@ -292,6 +422,7 @@ authenticated_command_handlers = {
...
@@ -292,6 +422,7 @@ authenticated_command_handlers = {
untagged
(
"
OK [UIDNEXT
"
+
(
base
.
last_msg
+
1
)
+
"
]
"
);
untagged
(
"
OK [UIDNEXT
"
+
(
base
.
last_msg
+
1
)
+
"
]
"
);
untagged
(
"
OK [UIDVALIDITY 0]
"
);
untagged
(
"
OK [UIDVALIDITY 0]
"
);
tagged
(
tag
,
"
OK
"
,
"
[READ-ONLY] Mailbox
"
+
sub
+
"
has been selected
"
);
tagged
(
tag
,
"
OK
"
,
"
[READ-ONLY] Mailbox
"
+
sub
+
"
has been selected
"
);
state
=
Selected
;
},
},
},
},
CREATE
:{
CREATE
:{
...
@@ -387,11 +518,138 @@ authenticated_command_handlers = {
...
@@ -387,11 +518,138 @@ authenticated_command_handlers = {
tagged
(
tag
,
"
OK
"
,
"
There you go.
"
);
tagged
(
tag
,
"
OK
"
,
"
There you go.
"
);
},
},
},
},
STATUS
:{
arguments
:
2
,
handler
:
function
(
args
)
{
var
tag
=
args
[
0
];
var
sub
=
getsub
(
args
[
1
]);
var
items
=
args
[
2
];
var
i
;
var
response
=
[];
if
(
typeof
(
items
)
!=
"
object
"
)
items
=
[
items
];
base
=
new
MsgBase
(
sub
);
if
(
base
==
undefined
||
(
!
base
.
open
()))
{
tagged
(
tag
,
"
NO
"
,
"
Can't find your mailbox
"
);
return
;
}
for
(
i
in
items
)
{
switch
(
items
[
i
].
toUpperCase
())
{
case
'
MESSAGES
'
:
response
.
push
(
"
MESSAGES
"
);
response
.
push
(
base
.
total_msgs
);
break
;
case
'
RECENT
'
:
response
.
push
(
"
RECENT
"
);
response
.
push
(
0
);
break
;
case
'
UIDNEXT
'
:
response
.
push
(
"
UIDNEXT
"
);
response
.
push
(
base
.
last_msg
+
1
);
break
;
case
'
UIDVALIDITY
'
:
response
.
push
(
"
UIDVALIDITY
"
);
response
.
push
(
0
);
break
;
case
'
UNSEEN
'
:
response
.
push
(
"
UNSEEN
"
);
response
.
push
(
base
.
total_msgs
);
break
;
}
}
base
.
close
();
untagged
(
"
STATUS {
"
+
(
args
[
1
].
length
)
+
"
}
\r\n
"
+
args
[
1
]
+
"
(
"
+
response
.
join
(
"
"
)
+
"
)
"
);
tagged
(
tag
,
"
OK
"
,
"
And that's the way it is.
"
);
},
},
APPEND
:{
arguments_valid
:
function
(
count
)
{
if
(
count
>=
2
&&
count
<=
4
)
return
(
true
);
return
(
false
);
},
handler
:
function
(
args
)
{
var
tag
=
args
[
0
];
tagged
(
tag
,
"
NO
"
,
"
No appending yet... sorry.
"
);
},
},
};
selected_command_handlers
=
{
CHECK
:{
arguments
:
0
,
handler
:
function
(
args
)
{
var
tag
=
args
[
0
];
tagged
(
tag
,
"
OK
"
,
"
Check.
"
);
},
},
CLOSE
:{
arguments
:
0
,
handler
:
function
(
args
)
{
var
tag
=
args
[
0
];
base
.
close
();
tagged
(
tag
,
"
OK
"
,
"
Closed.
"
);
state
=
Authenticated
;
},
},
EXPUNGE
:{
arguments
:
0
,
handler
:
function
(
args
)
{
var
tag
=
args
[
0
];
tagged
(
tag
,
"
NO
"
,
"
Can't expunge... wait for maintenance
"
);
},
},
SEARCH
:{
arguments_valid
:
function
(
count
)
{
return
(
count
>=
1
);
},
handler
:
function
(
args
)
{
var
tag
=
args
[
0
];
tagged
(
tag
,
"
NO
"
,
"
Can't search... I'm useless.
"
);
}
},
FETCH
:{
arguments
:
2
,
handler
:
function
(
args
)
{
var
tag
=
args
[
0
];
var
seq
=
parse_seq_set
(
args
[
1
],
false
);
var
data_items
=
parse_data_items
(
args
[
2
]);
var
i
;
for
(
i
in
seq
)
{
send_fetch_response
(
seq
[
i
],
data_items
);
}
//tagged(tag, "OK", "There they are!");
tagged
(
tag
,
"
NO
"
,
"
Can't fetch... I'm useless.
"
);
},
},
STORE
:{
arguments
:
3
,
handler
:
function
(
args
)
{
var
tag
=
args
[
0
];
tagged
(
tag
,
"
NO
"
,
"
This is read-only.
"
);
},
},
COPY
:{
arguments
:
2
,
handler
:
function
(
args
)
{
var
tag
=
args
[
0
];
tagged
(
tag
,
"
NO
"
,
"
Hah! You can't even FETCH yet and you want to COPY?!?!
"
);
},
},
UID
:{
UID
:{
arguments
:
3
,
arguments
:
3
,
handler
:
function
(
args
)
{
handler
:
function
(
args
)
{
var
tag
=
args
[
0
];
var
tag
=
args
[
0
];
tagged
(
tag
,
"
NO
"
,
"
Help, I'm useless.
"
);
tagged
(
tag
,
"
NO
"
,
"
Help, I'm useless.
"
);
},
},
}
}
...
@@ -403,7 +661,8 @@ while(1) {
...
@@ -403,7 +661,8 @@ while(1) {
line
=
client
.
socket
.
recvline
(
1024
,
300
);
line
=
client
.
socket
.
recvline
(
1024
,
300
);
if
(
line
!=
null
)
{
if
(
line
!=
null
)
{
debug_log
(
"
IMAP RECV:
"
+
line
);
debug_log
(
"
IMAP RECV:
"
+
line
);
parse_line
(
line
);
args
=
parse_line
();
execute_line
(
args
);
}
}
else
{
else
{
untagged
(
"
BYE No lolligaggers here!
"
);
untagged
(
"
BYE No lolligaggers here!
"
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment