NeoMutt  2025-01-09-117-gace867
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
dlg_query.c File Reference

Routines for querying an external address book. More...

#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "editor/lib.h"
#include "expando/lib.h"
#include "history/lib.h"
#include "key/lib.h"
#include "menu/lib.h"
#include "pattern/lib.h"
#include "send/lib.h"
#include "alias.h"
#include "expando.h"
#include "functions.h"
#include "gui.h"
#include "mutt_logging.h"
+ Include dependency graph for dlg_query.c:

Go to the source code of this file.

Functions

bool alias_to_addrlist (struct AddressList *al, struct Alias *alias)
 Turn an Alias into an AddressList.
 
static int query_make_entry (struct Menu *menu, int line, int max_cols, struct Buffer *buf)
 Format an Alias for the Menu - Implements Menu::make_entry() -.
 
static int query_tag (struct Menu *menu, int sel, int act)
 Tag an entry in the Query Menu - Implements Menu::tag() -.
 
int query_run (const char *s, bool verbose, struct AliasList *al, const struct ConfigSubset *sub)
 Run an external program to find Addresses.
 
static int query_window_observer (struct NotifyCallback *nc)
 Notification that a Window has changed - Implements observer_t -.
 
static struct SimpleDialogWindows query_dialog_new (struct AliasMenuData *mdata, const char *query)
 Create an Query Selection Dialog.
 
static bool dlg_query (struct Buffer *buf, struct AliasMenuData *mdata)
 Get the user to enter an Address Query -.
 
int query_complete (struct Buffer *buf, struct ConfigSubset *sub)
 Perform auto-complete using an Address Query.
 
void query_index (struct Mailbox *m, struct ConfigSubset *sub)
 Perform an Alias Query and display the results.
 

Variables

static const struct Mapping QueryHelp []
 Help Bar for the Address Query dialog.
 

Detailed Description

Routines for querying an external address book.

Authors
  • Richard Russon
  • Pietro Cerutti
  • Dennis Schön
  • Tóth János

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file dlg_query.c.

Function Documentation

◆ alias_to_addrlist()

bool alias_to_addrlist ( struct AddressList *  al,
struct Alias alias 
)

Turn an Alias into an AddressList.

Parameters
alAddressList to fill (must be empty)
aliasAlias to use
Return values
trueSuccess

Definition at line 119 of file dlg_query.c.

120{
121 if (!al || !TAILQ_EMPTY(al) || !alias)
122 return false;
123
124 mutt_addrlist_copy(al, &alias->addr, false);
125 if (!TAILQ_EMPTY(al))
126 {
127 struct Address *first = TAILQ_FIRST(al);
128 struct Address *second = TAILQ_NEXT(first, entries);
129 if (!second && !first->personal)
130 {
131 first->personal = buf_new(alias->name);
132 }
133
134 mutt_addrlist_to_intl(al, NULL);
135 }
136
137 return true;
138}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:765
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1293
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition: buffer.c:304
#define TAILQ_FIRST(head)
Definition: queue.h:780
#define TAILQ_NEXT(elm, field)
Definition: queue.h:889
#define TAILQ_EMPTY(head)
Definition: queue.h:778
An email address.
Definition: address.h:36
struct Buffer * personal
Real name of address.
Definition: address.h:37
char * name
Short name.
Definition: alias.h:36
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_run()

int query_run ( const char *  s,
bool  verbose,
struct AliasList *  al,
const struct ConfigSubset sub 
)

Run an external program to find Addresses.

Parameters
sString to match
verboseIf true, print progress messages
alAlias list to fill
subConfig items
Return values
0Success
-1Error

Definition at line 188 of file dlg_query.c.

189{
190 FILE *fp = NULL;
191 char *buf = NULL;
192 size_t buflen;
193 char *msg = NULL;
194 size_t msglen = 0;
195 char *tok = NULL;
196 char *next_tok = NULL;
197 struct Buffer *cmd = buf_pool_get();
198
199 const char *const c_query_command = cs_subset_string(sub, "query_command");
200 buf_file_expand_fmt_quote(cmd, c_query_command, s);
201
202 pid_t pid = filter_create(buf_string(cmd), NULL, &fp, NULL, NeoMutt->env);
203 if (pid < 0)
204 {
205 mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", buf_string(cmd));
206 buf_pool_release(&cmd);
207 return -1;
208 }
209 buf_pool_release(&cmd);
210
211 if (verbose)
212 mutt_message(_("Waiting for response..."));
213
214 struct Buffer *addr = buf_pool_get();
215 /* The query protocol first reads one NL-terminated line. If an error
216 * occurs, this is assumed to be an error message. Otherwise it's ignored. */
217 msg = mutt_file_read_line(msg, &msglen, fp, NULL, MUTT_RL_NO_FLAGS);
218 while ((buf = mutt_file_read_line(buf, &buflen, fp, NULL, MUTT_RL_NO_FLAGS)))
219 {
220 tok = buf;
221 next_tok = strchr(tok, '\t');
222 if (next_tok)
223 *next_tok++ = '\0';
224
225 if (*tok == '\0')
226 continue;
227
228 struct Alias *alias = alias_new();
229
230 if (next_tok)
231 {
232 tok = next_tok;
233 next_tok = strchr(tok, '\t');
234 if (next_tok)
235 *next_tok++ = '\0';
236
237 buf_printf(addr, "\"%s\" <%s>", tok, buf);
239
240 parse_alias_comments(alias, next_tok);
241 }
242 else
243 {
244 mutt_addrlist_parse(&alias->addr, buf); // Email address
245 }
246
247 TAILQ_INSERT_TAIL(al, alias, entries);
248 }
250
251 FREE(&buf);
252 mutt_file_fclose(&fp);
253 if (filter_wait(pid))
254 {
255 mutt_debug(LL_DEBUG1, "Error: %s\n", msg);
256 if (verbose)
257 mutt_error("%s", msg);
258 }
259 else
260 {
261 if (verbose)
262 mutt_message("%s", msg);
263 }
264 FREE(&msg);
265
266 return 0;
267}
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:480
void parse_alias_comments(struct Alias *alias, const char *com)
Parse the alias/query comment field.
Definition: commands.c:95
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:657
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:685
void buf_file_expand_fmt_quote(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1349
#define mutt_file_fclose(FP)
Definition: file.h:139
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:40
#define mutt_error(...)
Definition: logging2.h:93
#define mutt_message(...)
Definition: logging2.h:92
#define mutt_debug(LEVEL,...)
Definition: logging2.h:90
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:44
#define FREE(x)
Definition: memory.h:55
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:220
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition: filter.c:209
#define _(a)
Definition: message.h:28
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:866
A shortcut for an email address or addresses.
Definition: alias.h:35
String manipulation buffer.
Definition: buffer.h:36
Container for Accounts, Notifications.
Definition: neomutt.h:43
char ** env
Private copy of the environment variables.
Definition: neomutt.h:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_dialog_new()

static struct SimpleDialogWindows query_dialog_new ( struct AliasMenuData mdata,
const char *  query 
)
static

Create an Query Selection Dialog.

Parameters
mdataMenu data holding Aliases
queryInitial query string
Return values
objSimpleDialogWindows Tuple containing Dialog, SimpleBar and Menu pointers

Definition at line 301 of file dlg_query.c.

303{
305
306 struct Menu *menu = sdw.menu;
307
309 menu->tag = query_tag;
310 menu->max = ARRAY_SIZE(&mdata->ava);
311 mdata->title = mutt_str_dup(_("Query"));
312 menu->mdata = mdata;
313 menu->mdata_free = NULL; // Menu doesn't own the data
314
315 struct MuttWindow *win_menu = menu->win;
316
317 // Override the Simple Dialog's recalc()
318 win_menu->recalc = alias_recalc;
319
320 char title[256] = { 0 };
321 snprintf(title, sizeof(title), "%s: %s", mdata->title, query);
322 sbar_set_title(sdw.sbar, title);
323
324 // NT_COLOR is handled by the SimpleDialog
327
328 return sdw;
329}
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:87
static const struct Mapping QueryHelp[]
Help Bar for the Address Query dialog.
Definition: dlg_query.c:99
static int query_make_entry(struct Menu *menu, int line, int max_cols, struct Buffer *buf)
Format an Alias for the Menu - Implements Menu::make_entry() -.
Definition: dlg_query.c:145
static int query_tag(struct Menu *menu, int sel, int act)
Tag an entry in the Query Menu - Implements Menu::tag() -.
Definition: dlg_query.c:167
static int query_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: dlg_query.c:272
int alias_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: gui.c:43
int alias_recalc(struct MuttWindow *win)
Recalculate the display of the Alias Window - Implements MuttWindow::recalc() -.
Definition: gui.c:92
struct SimpleDialogWindows simple_dialog_new(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:132
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:191
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:254
@ WT_DLG_QUERY
Query Dialog, dlg_query()
Definition: mutt_window.h:91
@ NT_WINDOW
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:57
@ NT_CONFIG
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:43
void sbar_set_title(struct MuttWindow *win, const char *title)
Set the title for the Simple Bar.
Definition: sbar.c:227
char * title
Title for the status bar.
Definition: gui.h:62
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:51
Definition: lib.h:79
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:86
void(* mdata_free)(struct Menu *menu, void **ptr)
Definition: lib.h:161
int(* tag)(struct Menu *menu, int sel, int act)
Definition: lib.h:131
int(* make_entry)(struct Menu *menu, int line, int max_cols, struct Buffer *buf)
Definition: lib.h:106
void * mdata
Private data.
Definition: lib.h:147
int max
Number of entries in the menu.
Definition: lib.h:81
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:173
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:47
Tuple for the results of simple_dialog_new()
Definition: simple.h:35
struct MuttWindow * sbar
Simple Bar.
Definition: simple.h:37
struct Menu * menu
Menu.
Definition: simple.h:38
@ MENU_QUERY
Select from results of external query.
Definition: type.h:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_complete()

int query_complete ( struct Buffer buf,
struct ConfigSubset sub 
)

Perform auto-complete using an Address Query.

Parameters
bufBuffer for completion
subConfig item
Return values
0Always

Definition at line 399 of file dlg_query.c.

400{
401 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
402 mdata.search_state = search_state_new();
403
404 struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
405 const char *const c_query_command = cs_subset_string(sub, "query_command");
406 if (!c_query_command)
407 {
408 mutt_warning(_("Query command not defined"));
409 goto done;
410 }
411
412 query_run(buf_string(buf), true, &al, sub);
413 if (TAILQ_EMPTY(&al))
414 goto done;
415
416 mdata.al = &al;
417
418 struct Alias *a_first = TAILQ_FIRST(&al);
419 if (!TAILQ_NEXT(a_first, entries)) // only one response?
420 {
421 struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
422 if (alias_to_addrlist(&addr, a_first))
423 {
425 buf_reset(buf);
426 mutt_addrlist_write(&addr, buf, false);
427 mutt_addrlist_clear(&addr);
429 buf_addstr(buf, ", ");
430 }
431 goto done;
432 }
433
434 struct Alias *np = NULL;
435 TAILQ_FOREACH(np, mdata.al, entries)
436 {
437 alias_array_alias_add(&mdata.ava, np);
438 }
439
440 /* multiple results, choose from query menu */
441 if (!dlg_query(buf, &mdata))
442 goto done;
443
444 buf_reset(buf);
445 buf_alloc(buf, 8192);
446 struct AliasView *avp = NULL;
447 ARRAY_FOREACH(avp, &mdata.ava)
448 {
449 if (!avp->is_tagged)
450 continue;
451
452 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
453 if (alias_to_addrlist(&al_copy, avp->alias))
454 {
455 mutt_addrlist_to_local(&al_copy);
456 mutt_addrlist_write(&al_copy, buf, false);
457 mutt_addrlist_clear(&al_copy);
458 }
459 buf_addstr(buf, ", ");
460 }
461
462done:
463 ARRAY_FREE(&mdata.ava);
464 FREE(&mdata.title);
465 FREE(&mdata.limit);
467 aliaslist_clear(&al);
468 return 0;
469}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1460
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1378
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1206
void aliaslist_clear(struct AliasList *al)
Empty a List of Aliases.
Definition: alias.c:694
int alias_array_alias_add(struct AliasViewArray *ava, struct Alias *alias)
Add an Alias to the AliasViewArray.
Definition: array.c:47
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:214
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:204
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:58
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:337
int query_run(const char *s, bool verbose, struct AliasList *al, const struct ConfigSubset *sub)
Run an external program to find Addresses.
Definition: dlg_query.c:188
bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
Turn an Alias into an AddressList.
Definition: dlg_query.c:119
static bool dlg_query(struct Buffer *buf, struct AliasMenuData *mdata)
Get the user to enter an Address Query -.
Definition: dlg_query.c:342
#define mutt_warning(...)
Definition: logging2.h:91
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:782
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:694
void search_state_free(struct SearchState **ptr)
Free a SearchState.
Definition: search_state.c:51
struct SearchState * search_state_new(void)
Create a new SearchState.
Definition: search_state.c:39
AliasView array wrapper with Pattern information -.
Definition: gui.h:54
char * limit
Limit being used.
Definition: gui.h:60
struct AliasViewArray ava
All Aliases/Queries.
Definition: gui.h:55
struct SearchState * search_state
State of the current search.
Definition: gui.h:63
struct AliasList * al
Alias data.
Definition: gui.h:56
struct ConfigSubset * sub
Config items.
Definition: gui.h:57
GUI data wrapping an Alias.
Definition: gui.h:38
struct Alias * alias
Alias.
Definition: gui.h:46
bool is_tagged
Is it tagged?
Definition: gui.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_index()

void query_index ( struct Mailbox m,
struct ConfigSubset sub 
)

Perform an Alias Query and display the results.

Parameters
mMailbox
subConfig item

Definition at line 476 of file dlg_query.c.

477{
478 const char *const c_query_command = cs_subset_string(sub, "query_command");
479 if (!c_query_command)
480 {
481 mutt_warning(_("Query command not defined"));
482 return;
483 }
484
485 struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
486 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
487 mdata.al = &al;
488 mdata.search_state = search_state_new();
489
490 struct Buffer *buf = buf_pool_get();
491 if ((mw_get_field(_("Query: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
492 buf_is_empty(buf))
493 {
494 goto done;
495 }
496
497 query_run(buf_string(buf), false, &al, sub);
498 if (TAILQ_EMPTY(&al))
499 goto done;
500
501 struct Alias *np = NULL;
502 TAILQ_FOREACH(np, mdata.al, entries)
503 {
504 alias_array_alias_add(&mdata.ava, np);
505 }
506
507 if (!dlg_query(buf, &mdata))
508 goto done;
509
510 // Prepare the "To:" field of a new email
511 struct Email *e = email_new();
512 e->env = mutt_env_new();
513
514 struct AliasView *avp = NULL;
515 ARRAY_FOREACH(avp, &mdata.ava)
516 {
517 if (!avp->is_tagged)
518 continue;
519
520 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
521 if (alias_to_addrlist(&al_copy, avp->alias))
522 {
523 mutt_addrlist_copy(&e->env->to, &al_copy, false);
524 mutt_addrlist_clear(&al_copy);
525 }
526 }
527
528 mutt_send_message(SEND_REVIEW_TO, e, NULL, m, NULL, sub);
529
530done:
531 ARRAY_FREE(&mdata.ava);
532 FREE(&mdata.title);
533 FREE(&mdata.limit);
535 aliaslist_clear(&al);
536 buf_pool_release(&buf);
537}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
struct Email * email_new(void)
Create a new Email.
Definition: email.c:77
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:46
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:273
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:58
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailArray *ea, struct ConfigSubset *sub)
Send an email.
Definition: send.c:2034
#define SEND_REVIEW_TO
Allow the user to edit the To field.
Definition: send.h:56
The envelope/body of an email.
Definition: email.h:39
struct Envelope * env
Envelope information.
Definition: email.h:68
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ QueryHelp

const struct Mapping QueryHelp[]
static
Initial value:
= {
{ N_("Exit"), OP_EXIT },
{ N_("Mail"), OP_MAIL },
{ N_("New Query"), OP_QUERY },
{ N_("Make Alias"), OP_CREATE_ALIAS },
{ N_("Sort"), OP_SORT },
{ N_("Rev-Sort"), OP_SORT_REVERSE },
{ N_("Search"), OP_SEARCH },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Help Bar for the Address Query dialog.

Definition at line 99 of file dlg_query.c.