#include "sprinter.h"
#include "zlib-extra.h"
+static const char *
+_get_filename (notmuch_message_t *message, int index)
+{
+ notmuch_filenames_t *filenames = notmuch_message_get_filenames (message);
+ int i = 1;
+
+ for (;
+ notmuch_filenames_valid (filenames);
+ notmuch_filenames_move_to_next (filenames), i++) {
+ if (i >= index)
+ return notmuch_filenames_get (filenames);
+ }
+ return NULL;
+}
+
static const char *
_get_tags_as_string (const void *ctx, notmuch_message_t *message)
{
return 0;
}
+/* Output extra headers if configured with the `show.extra_headers'
+ * configuration option
+ */
+static void
+format_extra_headers_sprinter (sprinter_t *sp, GMimeMessage *message)
+{
+ GMimeHeaderList *header_list = g_mime_object_get_header_list (GMIME_OBJECT (message));
+
+ for (notmuch_config_values_t *extra_headers = notmuch_config_get_values (
+ sp->notmuch, NOTMUCH_CONFIG_EXTRA_HEADERS);
+ notmuch_config_values_valid (extra_headers);
+ notmuch_config_values_move_to_next (extra_headers)) {
+ GMimeHeader *header;
+ const char *header_name = notmuch_config_values_get (extra_headers);
+
+ header = g_mime_header_list_get_header (header_list, header_name);
+ if (header == NULL)
+ continue;
+
+ sp->map_key (sp, g_mime_header_get_name (header));
+ sp->string (sp, g_mime_header_get_value (header));
+ }
+}
+
void
format_headers_sprinter (sprinter_t *sp, GMimeMessage *message,
bool reply, const _notmuch_message_crypto_t *msg_crypto)
sp->string (sp, g_mime_message_get_date_string (sp, message));
}
+ /* Output extra headers the user has configured, if any */
+ if (! reply)
+ format_extra_headers_sprinter (sp, message);
sp->end (sp);
talloc_free (local);
}
sp->map_key (sp, "userid");
sp->string (sp, uid);
}
+ const char *email = g_mime_certificate_get_valid_email (certificate);
+ if (email) {
+ sp->map_key (sp, "email");
+ sp->string (sp, email);
+ }
}
} else if (certificate) {
const char *key_id = g_mime_certificate_get_fpr16 (certificate);
void
format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
+ int duplicate,
bool output_body,
bool include_html)
{
sp->begin_map (sp);
format_message_sprinter (sp, node->envelope_file);
+ sp->map_key (sp, "duplicate");
+ sp->integer (sp, duplicate > 0 ? duplicate : 1);
+
if (output_body) {
sp->map_key (sp, "body");
sp->begin_list (sp);
- format_part_sprinter (ctx, sp, mime_node_child (node, 0), true, include_html);
+ format_part_sprinter (ctx, sp, mime_node_child (node, 0), -1, true, include_html);
sp->end (sp);
}
}
for (i = 0; i < node->nchildren; i++)
- format_part_sprinter (ctx, sp, mime_node_child (node, i), true, include_html);
+ format_part_sprinter (ctx, sp, mime_node_child (node, i), -1, true, include_html);
/* Close content structures */
for (i = 0; i < nclose; i++)
mime_node_t *node, unused (int indent),
const notmuch_show_params_t *params)
{
- format_part_sprinter (ctx, sp, node, params->output_body, params->include_html);
+ format_part_sprinter (ctx, sp, node, params->duplicate, params->output_body,
+ params->include_html);
return NOTMUCH_STATUS_SUCCESS;
}
char buf[4096];
notmuch_status_t ret = NOTMUCH_STATUS_FILE_ERROR;
- filename = notmuch_message_get_filename (node->envelope_file);
+ filename = _get_filename (node->envelope_file, params->duplicate);
if (filename == NULL) {
fprintf (stderr, "Error: Cannot get message filename.\n");
goto DONE;
session_key_count_error = notmuch_message_count_properties (message, "session-key",
&session_keys);
- status = mime_node_open (local, message, &(params->crypto), &root);
+ status = mime_node_open (local, message, params->duplicate, &(params->crypto), &root);
if (status)
goto DONE;
part = mime_node_seek_dfs (root, (params->part < 0 ? 0 : params->part));
notmuch_thread_t *thread;
notmuch_messages_t *messages;
notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS;
+ int i;
+
+ if (params->offset < 0) {
+ unsigned count;
+ notmuch_status_t s = notmuch_query_count_threads (query, &count);
+ if (print_status_query ("notmuch show", query, s))
+ return 1;
+
+ params->offset += count;
+ if (params->offset < 0)
+ params->offset = 0;
+ }
status = notmuch_query_search_threads (query, &threads);
if (print_status_query ("notmuch show", query, status))
sp->begin_list (sp);
- for (;
- notmuch_threads_valid (threads);
- notmuch_threads_move_to_next (threads)) {
+ for (i = 0;
+ notmuch_threads_valid (threads) && (params->limit < 0 || i < params->offset + params->limit);
+ notmuch_threads_move_to_next (threads), i++) {
thread = notmuch_threads_get (threads);
+ if (i < params->offset) {
+ notmuch_thread_destroy (thread);
+ continue;
+ }
+
messages = notmuch_thread_get_toplevel_messages (thread);
if (messages == NULL)
notmuch_message_t *message;
notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS;
notmuch_bool_t excluded;
+ int i;
+
+ if (params->offset < 0) {
+ unsigned count;
+ notmuch_status_t s = notmuch_query_count_messages (query, &count);
+ if (print_status_query ("notmuch show", query, s))
+ return 1;
+
+ params->offset += count;
+ if (params->offset < 0)
+ params->offset = 0;
+ }
status = notmuch_query_search_messages (query, &messages);
if (print_status_query ("notmuch show", query, status))
sp->begin_list (sp);
- for (;
- notmuch_messages_valid (messages);
- notmuch_messages_move_to_next (messages)) {
+ for (i = 0;
+ notmuch_messages_valid (messages) && (params->limit < 0 || i < params->offset + params->limit);
+ notmuch_messages_move_to_next (messages), i++) {
+ if (i < params->offset) {
+ continue;
+ }
+
sp->begin_list (sp);
sp->begin_list (sp);
};
int
-notmuch_show_command (notmuch_config_t *config, unused(notmuch_database_t *notmuch),
- int argc, char *argv[])
+notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
{
- notmuch_database_t *notmuch;
notmuch_query_t *query;
char *query_string;
int opt_index, ret;
sprinter_t *sprinter;
notmuch_show_params_t params = {
.part = -1,
+ .duplicate = 0,
+ .offset = 0,
+ .limit = -1, /* unlimited */
.omit_excluded = true,
.output_body = true,
.crypto = { .decrypt = NOTMUCH_DECRYPT_AUTO },
bool entire_thread_set = false;
bool single_message;
bool unthreaded = FALSE;
- char *status_string = NULL;
+ notmuch_status_t status;
+ int sort = NOTMUCH_SORT_NEWEST_FIRST;
notmuch_opt_desc_t options[] = {
+ { .opt_keyword = &sort, .name = "sort", .keywords =
+ (notmuch_keyword_t []){ { "oldest-first", NOTMUCH_SORT_OLDEST_FIRST },
+ { "newest-first", NOTMUCH_SORT_NEWEST_FIRST },
+ { 0, 0 } } },
{ .opt_keyword = &format, .name = "format", .keywords =
(notmuch_keyword_t []){ { "json", NOTMUCH_FORMAT_JSON },
{ "text", NOTMUCH_FORMAT_TEXT },
{ .opt_bool = ¶ms.crypto.verify, .name = "verify" },
{ .opt_bool = ¶ms.output_body, .name = "body" },
{ .opt_bool = ¶ms.include_html, .name = "include-html" },
+ { .opt_int = ¶ms.duplicate, .name = "duplicate" },
+ { .opt_int = ¶ms.limit, .name = "limit" },
+ { .opt_int = ¶ms.offset, .name = "offset" },
{ .opt_inherit = notmuch_shared_options },
{ }
};
if (opt_index < 0)
return EXIT_FAILURE;
- notmuch_process_shared_options (argv[0]);
+ notmuch_process_shared_options (notmuch, argv[0]);
/* explicit decryption implies verification */
if (params.crypto.decrypt == NOTMUCH_DECRYPT_NOSTASH ||
/* specifying a part implies single message display */
single_message = params.part >= 0;
+ /* specifying a duplicate also implies single message display */
+ single_message = single_message || (params.duplicate > 0);
+
if (format == NOTMUCH_FORMAT_NOT_SPECIFIED) {
/* if part was requested and format was not specified, use format=raw */
if (params.part >= 0)
"Warning: --include-html only implemented for format=text, format=json and format=sexp\n");
}
- notmuch_database_mode_t mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
-
- if (params.crypto.decrypt == NOTMUCH_DECRYPT_TRUE)
- mode = NOTMUCH_DATABASE_MODE_READ_WRITE;
- if (notmuch_database_open_with_config (NULL,
- mode,
- _notmuch_config_get_path (config),
- NULL,
- ¬much,
- &status_string)) {
- if (status_string) {
- fputs (status_string, stderr);
- free (status_string);
+ if (params.crypto.decrypt == NOTMUCH_DECRYPT_TRUE) {
+ status = notmuch_database_reopen (notmuch, NOTMUCH_DATABASE_MODE_READ_WRITE);
+ if (status) {
+ fprintf (stderr, "Error reopening database for READ_WRITE: %s\n",
+ notmuch_status_to_string (status));
+ return EXIT_FAILURE;
}
-
- return EXIT_FAILURE;
}
- config = NULL;
-
- notmuch_exit_if_unmatched_db_uuid (notmuch);
-
query_string = query_string_from_args (notmuch, argc - opt_index, argv + opt_index);
if (query_string == NULL) {
fprintf (stderr, "Out of memory\n");
return EXIT_FAILURE;
}
- query = notmuch_query_create (notmuch, query_string);
- if (query == NULL) {
- fprintf (stderr, "Out of memory\n");
+ status = notmuch_query_create_with_syntax (notmuch, query_string,
+ shared_option_query_syntax (),
+ &query);
+ if (print_status_database ("notmuch show", notmuch, status))
return EXIT_FAILURE;
- }
+
+ notmuch_query_set_sort (query, sort);
/* Create structure printer. */
formatter = formatters[format];