Cross Reference: cmd-search.c
xref
: /
dovecot
/
src
/
imap
/
cmd-search.c
Home
History
Annotate
Line#
Navigate
Download
Search
only in
./
cmd-search.c revision 002e5f30f206552059cb087f77c715bbdcbf5ffe
1
N/A
/* Copyright (C) 2002 Timo Sirainen */
1
N/A
1
N/A
#
include
"
common.h
"
1
N/A
#
include
"
ostream.h
"
1
N/A
#
include
"
str.h
"
1
N/A
#
include
"
commands.h
"
1
N/A
#
include
"
imap-search.h
"
1
N/A
1
N/A
#
define
OUTBUF_SIZE
65536
1
N/A
1
N/A
struct
imap_search_context
{
1
N/A
struct
mailbox_transaction_context
*
trans
;
1
N/A
struct
mail_search_context
*
search_ctx
;
1
N/A
struct
mail
*
mail
;
1
N/A
1
N/A
struct
timeout
*
to
;
1
N/A
string_t
*
output_buf
;
1
N/A
1
N/A
unsigned
int
output_sent
:
1
;
1
N/A
};
1
N/A
1
N/A
static
struct
imap_search_context
*
1
N/A
imap_search_init
(
struct
client_command_context
*
cmd
,
const
char
*
charset
,
1
N/A
struct
mail_search_arg
*
sargs
)
1
N/A
{
1
N/A
struct
imap_search_context
*
ctx
;
1
N/A
1
N/A
ctx
=
p_new
(
cmd
->
pool
,
struct
imap_search_context
,
1
);
1
N/A
ctx
->
trans
=
mailbox_transaction_begin
(
cmd
->
client
->
mailbox
, 0);
1
N/A
ctx
->
search_ctx
=
mailbox_search_init
(
ctx
->
trans
,
charset
,
sargs
,
NULL
);
1
N/A
ctx
->
mail
=
mail_alloc
(
ctx
->
trans
, 0,
NULL
);
1
N/A
1
N/A
ctx
->
output_buf
=
str_new
(
default_pool
,
OUTBUF_SIZE
);
1
N/A
str_append
(
ctx
->
output_buf
,
"* SEARCH"
);
1
N/A
return
ctx
;
1
N/A
}
1
N/A
1
N/A
static
int
imap_search_deinit
(
struct
client_command_context
*
cmd
,
1
N/A
struct
imap_search_context
*
ctx
)
1
N/A
{
1
N/A
int
ret
;
1
N/A
1
N/A
mail_free
(&
ctx
->
mail
);
1
N/A
ret
=
mailbox_search_deinit
(&
ctx
->
search_ctx
);
1
N/A
1
N/A
if
(
mailbox_transaction_commit
(&
ctx
->
trans
, 0) < 0)
1
N/A
ret
= -
1
;
1
N/A
1
N/A
if
(
ctx
->
output_sent
|| (
ret
== 0 && !
cmd
->
cancel
)) {
1
N/A
str_append
(
ctx
->
output_buf
,
"\r\n"
);
1
N/A
o_stream_send
(
cmd
->
client
->
output
,
1
N/A
str_data
(
ctx
->
output_buf
),
1
N/A
str_len
(
ctx
->
output_buf
));
1
N/A
}
1
N/A
if
(
ctx
->
to
!=
NULL
)
1
N/A
timeout_remove
(&
ctx
->
to
);
1
N/A
str_free
(&
ctx
->
output_buf
);
1
N/A
1
N/A
cmd
->
context
=
NULL
;
1
N/A
return
ret
;
1
N/A
}
1
N/A
1
N/A
static
bool
cmd_search_more
(
struct
client_command_context
*
cmd
)
1
N/A
{
2
N/A
struct
imap_search_context
*
ctx
=
cmd
->
context
;
2
N/A
bool
tryagain
;
2
N/A
int
ret
;
2
N/A
1
N/A
if
(
cmd
->
cancel
) {
1
N/A
(
void
)
imap_search_deinit
(
cmd
,
ctx
);
1
N/A
return
TRUE
;
1
N/A
}
1
N/A
1
N/A
while
((
ret
=
mailbox_search_next_nonblock
(
ctx
->
search_ctx
,
ctx
->
mail
,
1
N/A
&
tryagain
)) > 0) {
1
N/A
if
(
str_len
(
ctx
->
output_buf
) >=
OUTBUF_SIZE
-
MAX_INT_STRLEN
) {
1
N/A
/* flush. this also causes us to lock the output. */
1
N/A
cmd
->
client
->
output_lock
=
cmd
;
1
N/A
o_stream_send
(
cmd
->
client
->
output
,
1
N/A
str_data
(
ctx
->
output_buf
),
1
N/A
str_len
(
ctx
->
output_buf
));
1
N/A
str_truncate
(
ctx
->
output_buf
, 0);
1
N/A
ctx
->
output_sent
=
TRUE
;
1
N/A
}
1
N/A
1
N/A
str_printfa
(
ctx
->
output_buf
,
" %u"
,
1
N/A
cmd
->
uid
?
ctx
->
mail
->
uid
:
ctx
->
mail
->
seq
);
1
N/A
}
1
N/A
if
(
tryagain
)
1
N/A
return
FALSE
;
1
N/A
1
N/A
if
(
imap_search_deinit
(
cmd
,
ctx
) < 0)
1
N/A
ret
= -
1
;
1
N/A
1
N/A
if
(
ret
< 0) {
1
N/A
client_send_storage_error
(
cmd
,
1
N/A
mailbox_get_storage
(
cmd
->
client
->
mailbox
));
1
N/A
return
TRUE
;
1
N/A
}
else
{
1
N/A
return
cmd_sync
(
cmd
,
MAILBOX_SYNC_FLAG_FAST
|
1
N/A
(
cmd
->
uid
? 0 :
MAILBOX_SYNC_FLAG_NO_EXPUNGES
),
1
N/A
0,
"OK Search completed."
);
1
N/A
}
1
N/A
}
1
N/A
1
N/A
static
void
cmd_search_more_callback
(
struct
client_command_context
*
cmd
)
1
N/A
{
1
N/A
struct
client
*
client
=
cmd
->
client
;
1
N/A
1
N/A
if
(
cmd_search_more
(
cmd
)) {
1
N/A
client_command_free
(
cmd
);
1
N/A
client_continue_pending_input
(
client
);
1
N/A
}
else
{
1
N/A
if
(
cmd
->
output_pending
)
1
N/A
o_stream_set_flush_pending
(
client
->
output
,
TRUE
);
1
N/A
}
1
N/A
}
1
N/A
1
N/A
bool
cmd_search
(
struct
client_command_context
*
cmd
)
1
N/A
{
1
N/A
struct
imap_search_context
*
ctx
;
1
N/A
struct
mail_search_arg
*
sargs
;
1
N/A
struct
imap_arg
*
args
;
1
N/A
int
args_count
;
1
N/A
const
char
*
error
, *
charset
;
1
N/A
1
N/A
args_count
=
imap_parser_read_args
(
cmd
->
parser
, 0, 0, &
args
);
1
N/A
if
(
args_count
<
1
) {
1
N/A
if
(
args_count
== -
2
)
1
N/A
return
FALSE
;
1
N/A
1
N/A
client_send_command_error
(
cmd
,
args_count
< 0 ?
NULL
:
1
N/A
"Missing SEARCH arguments."
);
1
N/A
return
TRUE
;
1
N/A
}
1
N/A
cmd
->
client
->
input_lock
=
NULL
;
1
N/A
1
N/A
if
(!
client_verify_open_mailbox
(
cmd
))
1
N/A
return
TRUE
;
1
N/A
1
N/A
if
(
args
->
type
==
IMAP_ARG_ATOM
&&
1
N/A
strcasecmp
(
IMAP_ARG_STR_NONULL
(
args
),
"CHARSET"
) == 0) {
1
N/A
/* CHARSET specified */
1
N/A
args
++;
1
N/A
if
(
args
->
type
!=
IMAP_ARG_ATOM
&&
1
N/A
args
->
type
!=
IMAP_ARG_STRING
) {
1
N/A
client_send_command_error
(
cmd
,
1
N/A
"Invalid charset argument."
);
1
N/A
return
TRUE
;
1
N/A
}
1
N/A
1
N/A
charset
=
IMAP_ARG_STR
(
args
);
1
N/A
args
++;
1
N/A
}
else
{
1
N/A
charset
=
NULL
;
1
N/A
}
1
N/A
1
N/A
sargs
=
imap_search_args_build
(
cmd
->
pool
,
cmd
->
client
->
mailbox
,
1
N/A
args
, &
error
);
1
N/A
if
(
sargs
==
NULL
) {
1
N/A
/* error in search arguments */
1
N/A
client_send_tagline
(
cmd
,
t_strconcat
(
"NO "
,
error
,
NULL
));
1
N/A
return
TRUE
;
1
N/A
}
1
N/A
1
N/A
ctx
=
imap_search_init
(
cmd
,
charset
,
sargs
);
1
N/A
cmd
->
func
=
cmd_search_more
;
1
N/A
cmd
->
context
=
ctx
;
1
N/A
1
N/A
if
(
cmd_search_more
(
cmd
))
1
N/A
return
TRUE
;
1
N/A
1
N/A
/* we could have moved onto syncing by now */
1
N/A
if
(
cmd
->
func
==
cmd_search_more
)
1
N/A
ctx
->
to
=
timeout_add
(0,
cmd_search_more_callback
,
cmd
);
1
N/A
return
FALSE
;
1
N/A
}
1
N/A