diff options
Diffstat (limited to 'src/fe-common/core')
23 files changed, 517 insertions, 170 deletions
diff --git a/src/fe-common/core/Makefile.am b/src/fe-common/core/Makefile.am index 6efff411..cf4e8ee3 100644 --- a/src/fe-common/core/Makefile.am +++ b/src/fe-common/core/Makefile.am @@ -38,17 +38,24 @@ libfe_common_core_a_SOURCES = \ windows-layout.c \ fe-windows.c +if HAVE_CAPSICUM +libfe_common_core_a_SOURCES += \ + fe-capsicum.c +endif + pkginc_fe_common_coredir=$(pkgincludedir)/src/fe-common/core pkginc_fe_common_core_HEADERS = \ command-history.h \ chat-completion.h \ completion.h \ + fe-capsicum.h \ fe-channels.h \ fe-common-core.h \ fe-core-commands.h \ fe-exec.h \ fe-messages.h \ fe-queries.h \ + fe-settings.h \ fe-tls.h \ formats.h \ hilight-text.h \ diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c index 1f00feaf..97cd0565 100644 --- a/src/fe-common/core/chat-completion.c +++ b/src/fe-common/core/chat-completion.c @@ -1011,13 +1011,17 @@ static void sig_complete_target(GList **list, WINDOW_REC *window, } } +static void event_text(const char *data, SERVER_REC *server, WI_ITEM_REC *item); + /* expand \n, \t and \\ */ static char *expand_escapes(const char *line, SERVER_REC *server, WI_ITEM_REC *item) { char *ptr, *ret; - int chr; + const char *prev; + int chr; + prev = line; ret = ptr = g_malloc(strlen(line)+1); for (; *line != '\0'; line++) { if (*line != '\\') { @@ -1036,9 +1040,11 @@ static char *expand_escapes(const char *line, SERVER_REC *server, /* newline .. we need to send another "send text" event to handle it (or actually the text before the newline..) */ - if (ret != ptr) { - *ptr = '\0'; - signal_emit("send text", 3, ret, server, item); + if (prev != line) { + char *prev_line = g_strndup(prev, (line - prev) - 1); + event_text(prev_line, server, item); + g_free(prev_line); + prev = line + 1; ptr = ret; } } else if (chr != -1) { diff --git a/src/fe-common/core/command-history.c b/src/fe-common/core/command-history.c index 55474b1b..32d7adaa 100644 --- a/src/fe-common/core/command-history.c +++ b/src/fe-common/core/command-history.c @@ -30,10 +30,93 @@ #include "command-history.h" /* command history */ +static GList *history_entries; static HISTORY_REC *global_history; static int window_history; static GSList *histories; +static HISTORY_ENTRY_REC *history_entry_new(HISTORY_REC *history, const char *text) +{ + HISTORY_ENTRY_REC *entry; + + entry = g_new0(HISTORY_ENTRY_REC, 1); + entry->text = g_strdup(text); + entry->history = history; + entry->time = time(NULL); + + return entry; +} + +static void history_entry_destroy(HISTORY_ENTRY_REC *entry) +{ + g_free((char *)entry->text); + g_free(entry); +} + +GList *command_history_list_last(HISTORY_REC *history) +{ + GList *link; + + link = g_list_last(history_entries); + while (link != NULL && history != NULL && ((HISTORY_ENTRY_REC *)link->data)->history != history) { + link = link->prev; + } + + return link; +} + +GList *command_history_list_first(HISTORY_REC *history) +{ + GList *link; + + link = history_entries; + while (link != NULL && history != NULL && ((HISTORY_ENTRY_REC *)link->data)->history != history) { + link = link->next; + } + + return link; +} + +GList *command_history_list_prev(HISTORY_REC *history, GList *pos) +{ + GList *link; + + link = pos != NULL ? pos->prev : NULL; + while (link != NULL && history != NULL && ((HISTORY_ENTRY_REC *)link->data)->history != history) { + link = link->prev; + } + + return link; +} + +GList *command_history_list_next(HISTORY_REC *history, GList *pos) +{ + GList *link; + + link = pos != NULL ? pos->next : NULL; + while (link != NULL && history != NULL && ((HISTORY_ENTRY_REC *)link->data)->history != history) { + link = link->next; + } + + return link; +} + +static void command_history_clear_pos_for_unlink_func(HISTORY_REC *history, GList* link) +{ + if (history->pos == link) { + history->pos = command_history_list_next(history, link); + history->redo = 1; + } +} + +static void history_list_delete_link_and_destroy(GList *link) +{ + g_slist_foreach(histories, + (GFunc) command_history_clear_pos_for_unlink_func, link); + history_entry_destroy(link->data); + history_entries = g_list_delete_link(history_entries, link); +} + void command_history_add(HISTORY_REC *history, const char *text) { GList *link; @@ -41,21 +124,19 @@ void command_history_add(HISTORY_REC *history, const char *text) g_return_if_fail(history != NULL); g_return_if_fail(text != NULL); - link = g_list_last(history->list); - if (link != NULL && g_strcmp0(link->data, text) == 0) - return; /* same as previous entry */ + link = command_history_list_last(history); + if (link != NULL && g_strcmp0(((HISTORY_ENTRY_REC *)link->data)->text, text) == 0) + return; /* same as previous entry */ if (settings_get_int("max_command_history") < 1 || history->lines < settings_get_int("max_command_history")) history->lines++; else { - link = history->list; - g_free(link->data); - history->list = g_list_remove_link(history->list, link); - g_list_free_1(link); + link = command_history_list_first(history); + history_list_delete_link_and_destroy(link); } - history->list = g_list_append(history->list, g_strdup(text)); + history_entries = g_list_append(history_entries, history_entry_new(history, text)); } HISTORY_REC *command_history_find(HISTORY_REC *history) @@ -87,6 +168,61 @@ HISTORY_REC *command_history_find_name(const char *name) return NULL; } +static int history_entry_after_time_sort(const HISTORY_ENTRY_REC *a, const HISTORY_ENTRY_REC *b) +{ + return a->time == b->time ? 1 : a->time - b->time; +} + +void command_history_load_entry(time_t history_time, HISTORY_REC *history, const char *text) +{ + HISTORY_ENTRY_REC *entry; + + g_return_if_fail(history != NULL); + g_return_if_fail(text != NULL); + + entry = g_new0(HISTORY_ENTRY_REC, 1); + entry->text = g_strdup(text); + entry->history = history; + entry->time = history_time; + + history->lines++; + + history_entries = g_list_insert_sorted(history_entries, entry, (GCompareFunc)history_entry_after_time_sort); +} + +static int history_entry_find_func(const HISTORY_ENTRY_REC *data, const HISTORY_ENTRY_REC *user_data) +{ + if ((user_data->time == -1 || (data->time == user_data->time)) && + (user_data->history == NULL || (data->history == user_data->history)) && + g_strcmp0(data->text, user_data->text) == 0) { + return 0; + } else { + return -1; + } +} + +gboolean command_history_delete_entry(time_t history_time, HISTORY_REC *history, const char *text) +{ + GList *link; + HISTORY_ENTRY_REC entry; + + g_return_val_if_fail(history != NULL, FALSE); + g_return_val_if_fail(text != NULL, FALSE); + + entry.text = text; + entry.history = history; + entry.time = history_time; + + link = g_list_find_custom(history_entries, &entry, (GCompareFunc)history_entry_find_func); + if (link != NULL) { + ((HISTORY_ENTRY_REC *)link->data)->history->lines--; + history_list_delete_link_and_destroy(link); + return TRUE; + } else { + return FALSE; + } +} + HISTORY_REC *command_history_current(WINDOW_REC *window) { HISTORY_REC *rec; @@ -104,32 +240,44 @@ HISTORY_REC *command_history_current(WINDOW_REC *window) return global_history; } -const char *command_history_prev(WINDOW_REC *window, const char *text) +static const char *command_history_prev_int(WINDOW_REC *window, const char *text, gboolean global) { HISTORY_REC *history; GList *pos; history = command_history_current(window); pos = history->pos; + history->redo = 0; if (pos != NULL) { /* don't go past the first entry (no wrap around) */ - if (history->pos->prev != NULL) - history->pos = history->pos->prev; + GList *prev = command_history_list_prev(global ? NULL : history, history->pos); + if (prev != NULL) + history->pos = prev; } else { - history->pos = g_list_last(history->list); + history->pos = command_history_list_last(global ? NULL : history); } if (*text != '\0' && - (pos == NULL || g_strcmp0(pos->data, text) != 0)) { + (pos == NULL || g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) != 0)) { /* save the old entry to history */ command_history_add(history, text); } - return history->pos == NULL ? text : history->pos->data; + return history->pos == NULL ? text : ((HISTORY_ENTRY_REC *)history->pos->data)->text; } -const char *command_history_next(WINDOW_REC *window, const char *text) +const char *command_history_prev(WINDOW_REC *window, const char *text) +{ + return command_history_prev_int(window, text, FALSE); +} + +const char *command_global_history_prev(WINDOW_REC *window, const char *text) +{ + return command_history_prev_int(window, text, TRUE); +} + +static const char *command_history_next_int(WINDOW_REC *window, const char *text, gboolean global) { HISTORY_REC *history; GList *pos; @@ -137,15 +285,43 @@ const char *command_history_next(WINDOW_REC *window, const char *text) history = command_history_current(window); pos = history->pos; - if (pos != NULL) - history->pos = history->pos->next; + if (!(history->redo) && pos != NULL) + history->pos = command_history_list_next(global ? NULL : history, history->pos); + history->redo = 0; if (*text != '\0' && - (pos == NULL || g_strcmp0(pos->data, text) != 0)) { + (pos == NULL || g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) != 0)) { /* save the old entry to history */ command_history_add(history, text); } - return history->pos == NULL ? "" : history->pos->data; + return history->pos == NULL ? "" : ((HISTORY_ENTRY_REC *)history->pos->data)->text; +} + +const char *command_history_next(WINDOW_REC *window, const char *text) +{ + return command_history_next_int(window, text, FALSE); +} + +const char *command_global_history_next(WINDOW_REC *window, const char *text) +{ + return command_history_next_int(window, text, TRUE); +} + +const char *command_history_delete_current(WINDOW_REC *window, const char *text) +{ + HISTORY_REC *history; + GList *pos; + + history = command_history_current(window); + pos = history->pos; + + if (pos != NULL && g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) == 0) { + ((HISTORY_ENTRY_REC *)pos->data)->history->lines--; + history_list_delete_link_and_destroy(pos); + } + + history->redo = 0; + return history->pos == NULL ? "" : ((HISTORY_ENTRY_REC *)history->pos->data)->text; } void command_history_clear_pos_func(HISTORY_REC *history, gpointer user_data) @@ -175,12 +351,17 @@ HISTORY_REC *command_history_create(const char *name) void command_history_clear(HISTORY_REC *history) { + GList *link, *next; + g_return_if_fail(history != NULL); command_history_clear_pos_func(history, NULL); - g_list_foreach(history->list, (GFunc) g_free, NULL); - g_list_free(history->list); - history->list = NULL; + link = command_history_list_first(history); + while (link != NULL) { + next = command_history_list_next(history, link); + history_list_delete_link_and_destroy(link); + link = next; + } history->lines = 0; } @@ -264,8 +445,8 @@ static char *special_history_func(const char *text, void *item, int *free_ret) ret = NULL; history = command_history_current(window); - for (tmp = history->list; tmp != NULL; tmp = tmp->next) { - const char *line = tmp->data; + for (tmp = command_history_list_first(history); tmp != NULL; tmp = command_history_list_next(history, tmp)) { + const char *line = ((HISTORY_ENTRY_REC *)tmp->data)->text; if (match_wildcards(findtext, line)) { *free_ret = TRUE; @@ -289,6 +470,8 @@ void command_history_init(void) special_history_func_set(special_history_func); + history_entries = NULL; + global_history = command_history_create(NULL); read_settings(); @@ -308,4 +491,6 @@ void command_history_deinit(void) signal_remove("setup changed", (SIGNAL_FUNC) read_settings); command_history_destroy(global_history); + + g_list_free_full(history_entries, (GDestroyNotify) history_entry_destroy); } diff --git a/src/fe-common/core/command-history.h b/src/fe-common/core/command-history.h index 45126092..ed093415 100644 --- a/src/fe-common/core/command-history.h +++ b/src/fe-common/core/command-history.h @@ -6,12 +6,19 @@ typedef struct { char *name; - GList *list, *pos; + GList *pos; int lines; int refcount; + int redo:1; } HISTORY_REC; +typedef struct { + const char *text; + HISTORY_REC *history; + time_t time; +} HISTORY_ENTRY_REC; + HISTORY_REC *command_history_find(HISTORY_REC *history); HISTORY_REC *command_history_find_name(const char *name); @@ -21,9 +28,19 @@ void command_history_init(void); void command_history_deinit(void); void command_history_add(HISTORY_REC *history, const char *text); +void command_history_load_entry(time_t time, HISTORY_REC *history, const char *text); +gboolean command_history_delete_entry(time_t history_time, HISTORY_REC *history, const char *text); + +GList *command_history_list_last(HISTORY_REC *history); +GList *command_history_list_first(HISTORY_REC *history); +GList *command_history_list_prev(HISTORY_REC *history, GList *pos); +GList *command_history_list_next(HISTORY_REC *history, GList *pos); const char *command_history_prev(WINDOW_REC *window, const char *text); const char *command_history_next(WINDOW_REC *window, const char *text); +const char *command_global_history_prev(WINDOW_REC *window, const char *text); +const char *command_global_history_next(WINDOW_REC *window, const char *text); +const char *command_history_delete_current(WINDOW_REC *window, const char *text); void command_history_clear_pos(WINDOW_REC *window); diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index a97adc21..fd452e5c 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -137,8 +137,9 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i int old_startpos, old_wordlen; GString *result; - char *word, *wordstart, *linestart, *ret; - int continue_complete, want_space; + const char *cmdchars; + char *word, *wordstart, *linestart, *ret, *data; + int continue_complete, want_space, expand_escapes; g_return_val_if_fail(line != NULL, NULL); g_return_val_if_fail(pos != NULL, NULL); @@ -186,12 +187,18 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i char *old; old = linestart; - linestart = *linestart == '\0' ? - g_strdup(word) : - g_strdup_printf("%s%c%s", - /* do not accidentally duplicate the word separator */ - line == wordstart - 1 ? "" : linestart, - old_wordstart[-1], word); + /* we want to move word into linestart */ + if (*linestart == '\0') { + linestart = g_strdup(word); + } else { + GString *str = g_string_new(linestart); + if (old_wordstart[-1] != str->str[str->len - 1]) { + /* do not accidentally duplicate the word separator */ + g_string_append_c(str, old_wordstart[-1]); + } + g_string_append(str, word); + linestart = g_string_free(str, FALSE); + } g_free(old); g_free(word); @@ -241,14 +248,24 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i if (complist == NULL) return NULL; + /* get the cmd char */ + cmdchars = settings_get_str("cmdchars"); + + /* get the expand_escapes setting */ + expand_escapes = settings_get_bool("expand_escapes"); + + /* escape if the word doesn't begin with '/' and expand_escapes are turned on */ + data = strchr(cmdchars, *line) == NULL && expand_escapes ? + escape_string(complist->data) : g_strdup(complist->data); + /* word completed */ - *pos = startpos+strlen(complist->data); + *pos = startpos + strlen(data); /* replace the word in line - we need to return a full new line */ result = g_string_new(line); g_string_erase(result, startpos, wordlen); - g_string_insert(result, startpos, complist->data); + g_string_insert(result, startpos, data); if (want_space) { if (!isseparator(result->str[*pos])) @@ -256,13 +273,17 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i (*pos)++; } - wordlen = strlen(complist->data); + wordlen = strlen(data); last_line_pos = *pos; g_free_not_null(last_line); last_line = g_strdup(result->str); ret = result->str; g_string_free(result, FALSE); + + /* free the data */ + g_free(data); + return ret; } @@ -306,6 +327,10 @@ GList *filename_complete(const char *path, const char *default_path) g_return_val_if_fail(path != NULL, NULL); + if (path[0] == '\0') { + return NULL; + } + list = NULL; /* get directory part of the path - expand ~/ */ @@ -335,7 +360,14 @@ GList *filename_complete(const char *path, const char *default_path) g_free_and_null(dir); } - basename = g_path_get_basename(path); + len = strlen(path); + /* g_path_get_basename() returns the component before the last slash if + * the path ends with a directory separator, that's not what we want */ + if (len > 0 && path[len - 1] == G_DIR_SEPARATOR) { + basename = g_strdup(""); + } else { + basename = g_path_get_basename(path); + } len = strlen(basename); /* add all files in directory to completion list */ diff --git a/src/fe-common/core/fe-capsicum.c b/src/fe-common/core/fe-capsicum.c new file mode 100644 index 00000000..54a43d27 --- /dev/null +++ b/src/fe-common/core/fe-capsicum.c @@ -0,0 +1,63 @@ +/* + fe-capsicum.c : irssi + + Copyright (C) 2017 Edward Tomasz Napierala <trasz@FreeBSD.org> + + This software was developed by SRI International and the University of + Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + ("CTSRD"), as part of the DARPA CRASH research programme. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "module.h" +#include "fe-capsicum.h" +#include "levels.h" +#include "module-formats.h" +#include "printtext.h" +#include "signals.h" + +static void capability_mode_enabled(void) +{ + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CAPSICUM_ENABLED); +} + +static void capability_mode_disabled(void) +{ + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CAPSICUM_DISABLED); +} + +static void capability_mode_failed(gchar *msg) +{ + + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_CAPSICUM_FAILED, msg); +} + +void fe_capsicum_init(void) +{ + + signal_add("capability mode enabled", (SIGNAL_FUNC) capability_mode_enabled); + signal_add("capability mode disabled", (SIGNAL_FUNC) capability_mode_disabled); + signal_add("capability mode failed", (SIGNAL_FUNC) capability_mode_failed); +} + +void fe_capsicum_deinit(void) +{ + signal_remove("capability mode enabled", (SIGNAL_FUNC) capability_mode_enabled); + signal_remove("capability mode disabled", (SIGNAL_FUNC) capability_mode_disabled); + signal_remove("capability mode failed", (SIGNAL_FUNC) capability_mode_failed); +} diff --git a/src/fe-common/core/fe-capsicum.h b/src/fe-common/core/fe-capsicum.h new file mode 100644 index 00000000..a7cb743b --- /dev/null +++ b/src/fe-common/core/fe-capsicum.h @@ -0,0 +1,7 @@ +#ifndef __FE_CAPSICUM_H +#define __FE_CAPSICUM_H + +void fe_capsicum_init(void); +void fe_capsicum_deinit(void); + +#endif diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index 8e434ab5..5cad51a7 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -278,9 +278,9 @@ static void cmd_channel_add_modify(const char *data, gboolean add) rec = channel_setup_find(channel, chatnet); if (rec == NULL) { if (add == FALSE) { - cmd_params_free(free_arg); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CHANSETUP_NOT_FOUND, channel, chatnet); + cmd_params_free(free_arg); return; } diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index 791f56d4..209c2d9e 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -32,6 +32,9 @@ #include "special-vars.h" #include "fe-core-commands.h" #include "fe-queries.h" +#ifdef HAVE_CAPSICUM +#include "fe-capsicum.h" +#endif #include "hilight-text.h" #include "command-history.h" #include "completion.h" @@ -179,6 +182,9 @@ void fe_common_core_init(void) fe_server_init(); fe_settings_init(); fe_tls_init(); +#ifdef HAVE_CAPSICUM + fe_capsicum_init(); +#endif windows_init(); window_activity_init(); window_commands_init(); @@ -221,6 +227,9 @@ void fe_common_core_deinit(void) fe_server_deinit(); fe_settings_deinit(); fe_tls_deinit(); +#ifdef HAVE_CAPSICUM + fe_capsicum_deinit(); +#endif windows_deinit(); window_activity_deinit(); window_commands_deinit(); diff --git a/src/fe-common/core/fe-core-commands.c b/src/fe-common/core/fe-core-commands.c index 97a246ec..fb98cc25 100644 --- a/src/fe-common/core/fe-core-commands.c +++ b/src/fe-common/core/fe-core-commands.c @@ -28,6 +28,9 @@ #include "settings.h" #include "irssi-version.h" #include "servers.h" +#ifdef HAVE_CAPSICUM +#include "capsicum.h" +#endif #include "fe-windows.h" #include "printtext.h" @@ -120,6 +123,9 @@ static void cmd_cat(const char *data) GIOChannel *handle; GString *buf; gsize tpos; +#ifdef HAVE_CAPSICUM + int fd; +#endif if (!cmd_get_params(data, &free_arg, 2, &fname, &fposstr)) return; @@ -128,7 +134,15 @@ static void cmd_cat(const char *data) fpos = atoi(fposstr); cmd_params_free(free_arg); +#ifdef HAVE_CAPSICUM + fd = capsicum_open_wrapper(fname, O_RDONLY, 0); + if (fd > 0) + handle = g_io_channel_unix_new(fd); + else + handle = NULL; +#else handle = g_io_channel_new_file(fname, "r", NULL); +#endif g_free(fname); if (handle == NULL) { diff --git a/src/fe-common/core/fe-exec.c b/src/fe-common/core/fe-exec.c index 36990866..c1739d39 100644 --- a/src/fe-common/core/fe-exec.c +++ b/src/fe-common/core/fe-exec.c @@ -613,7 +613,7 @@ static void sig_exec_input(PROCESS_REC *rec, const char *text) str = g_strconcat(rec->target_nick ? "-nick " : rec->target_channel ? "-channel " : "", - rec->target, " ", text, NULL); + rec->target, " ", *text == '\0' ? " " : text, NULL); signal_emit(rec->notice ? "command notice" : "command msg", 3, str, server, item); g_free(str); diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index 800e881d..03fd4dd2 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -58,13 +58,8 @@ static void ignore_print(int index, IGNORE_REC *rec) g_string_append(options, "-regexp "); if (rec->pattern == NULL) g_string_append(options, "[INVALID! -pattern missing] "); -#ifdef USE_GREGEX else if (rec->preg == NULL) g_string_append(options, "[INVALID!] "); -#else - else if (!rec->regexp_compiled) - g_string_append(options, "[INVALID!] "); -#endif } if (rec->fullword) g_string_append(options, "-full "); if (rec->replies) g_string_append(options, "-replies "); diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index 5bc5c4e1..0fed8642 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -30,6 +30,9 @@ #include "special-vars.h" #include "settings.h" #include "lib-config/iconfig.h" +#ifdef HAVE_CAPSICUM +#include "capsicum.h" +#endif #include "fe-windows.h" #include "window-items.h" @@ -49,8 +52,6 @@ static THEME_REC *log_theme; static int skip_next_printtext; static char *log_theme_name; -static int log_dir_create_mode; - static char **autolog_ignore_targets; static char *log_colorizer_strip(const char *str) @@ -453,7 +454,11 @@ static void autolog_open(SERVER_REC *server, const char *server_tag, log_item_add(log, LOG_ITEM_TARGET, target, server_tag); dir = g_path_get_dirname(log->real_fname); +#ifdef HAVE_CAPSICUM + capsicum_mkdir_with_parents_wrapper(dir, log_dir_create_mode); +#else g_mkdir_with_parents(dir, log_dir_create_mode); +#endif g_free(dir); log->temp = TRUE; @@ -676,7 +681,6 @@ static void sig_theme_destroyed(THEME_REC *theme) static void read_settings(void) { int old_autolog = autolog_level; - int log_file_create_mode; g_free_not_null(autolog_path); autolog_path = g_strdup(settings_get_str("autolog_path")); @@ -704,12 +708,6 @@ static void read_settings(void) log_theme = log_theme_name == NULL ? NULL : theme_load(log_theme_name); - log_file_create_mode = octal2dec(settings_get_int("log_create_mode")); - log_dir_create_mode = log_file_create_mode; - if (log_file_create_mode & 0400) log_dir_create_mode |= 0100; - if (log_file_create_mode & 0040) log_dir_create_mode |= 0010; - if (log_file_create_mode & 0004) log_dir_create_mode |= 0001; - if (autolog_ignore_targets != NULL) g_strfreev(autolog_ignore_targets); diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index f4c1d3ee..074a83f3 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -117,7 +117,18 @@ static void cmd_server_add_modify(const char *data, gboolean add) return; if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - port = *portstr == '\0' ? DEFAULT_SERVER_ADD_PORT : atoi(portstr); + + value = g_hash_table_lookup(optlist, "port"); + + if (*portstr != '\0') + port = atoi(portstr); + else if (value != NULL && *value != '\0') + port = atoi(value); + else if (g_hash_table_lookup(optlist, "tls") || + g_hash_table_lookup(optlist, "ssl")) + port = DEFAULT_SERVER_ADD_TLS_PORT; + else + port = DEFAULT_SERVER_ADD_PORT; chatnet = g_hash_table_lookup(optlist, "network"); @@ -125,9 +136,9 @@ static void cmd_server_add_modify(const char *data, gboolean add) if (rec == NULL) { if (add == FALSE) { - cmd_params_free(free_arg); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_SETUPSERVER_NOT_FOUND, addr, port); + cmd_params_free(free_arg); return; } @@ -139,8 +150,8 @@ static void cmd_server_add_modify(const char *data, gboolean add) rec->address = g_strdup(addr); rec->port = port; } else { - value = g_hash_table_lookup(optlist, "port"); - if (value != NULL && *value != '\0') rec->port = atoi(value); + if (*portstr != '\0' || g_hash_table_lookup(optlist, "port")) + rec->port = port; if (*password != '\0') g_free_and_null(rec->password); if (g_hash_table_lookup(optlist, "host")) { @@ -154,8 +165,14 @@ static void cmd_server_add_modify(const char *data, gboolean add) else if (g_hash_table_lookup(optlist, "4")) rec->family = AF_INET; - if (g_hash_table_lookup(optlist, "tls") || g_hash_table_lookup(optlist, "ssl")) + if (g_hash_table_lookup(optlist, "tls") || g_hash_table_lookup(optlist, "ssl")) { rec->use_tls = TRUE; + } + else if (g_hash_table_lookup(optlist, "notls") || g_hash_table_lookup(optlist, "nossl")) { + rec->use_tls = FALSE; + /* tls_verify implies use_tls, disable it explicitly */ + rec->tls_verify = FALSE; + } value = g_hash_table_lookup(optlist, "tls_cert"); if (value == NULL) @@ -177,6 +194,8 @@ static void cmd_server_add_modify(const char *data, gboolean add) if (g_hash_table_lookup(optlist, "tls_verify") || g_hash_table_lookup(optlist, "ssl_verify")) rec->tls_verify = TRUE; + else if (g_hash_table_lookup(optlist, "notls_verify") || g_hash_table_lookup(optlist, "nossl_verify")) + rec->tls_verify = FALSE; value = g_hash_table_lookup(optlist, "tls_cafile"); if (value == NULL) @@ -434,8 +453,8 @@ void fe_server_init(void) command_bind_first("server", NULL, (SIGNAL_FUNC) server_command); command_bind_first("disconnect", NULL, (SIGNAL_FUNC) server_command); - command_set_options("server add", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +ssl_ciphers +ssl_fingerprint tls +tls_cert +tls_pkey +tls_pass tls_verify +tls_cafile +tls_capath +tls_ciphers +tls_pinned_cert +tls_pinned_pubkey auto noauto proxy noproxy -host -port noautosendcmd"); - command_set_options("server modify", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +ssl_ciphers +ssl_fingerprint tls +tls_cert +tls_pkey +tls_pass tls_verify +tls_cafile +tls_capath +tls_ciphers +tls_pinned_cert +tls_pinned_pubkey auto noauto proxy noproxy -host -port noautosendcmd"); + command_set_options("server add", "4 6 !! ssl nossl +ssl_cert +ssl_pkey +ssl_pass ssl_verify nossl_verify +ssl_cafile +ssl_capath +ssl_ciphers +ssl_fingerprint tls notls +tls_cert +tls_pkey +tls_pass tls_verify notls_verify +tls_cafile +tls_capath +tls_ciphers +tls_pinned_cert +tls_pinned_pubkey auto noauto proxy noproxy -host -port noautosendcmd"); + command_set_options("server modify", "4 6 !! ssl nossl +ssl_cert +ssl_pkey +ssl_pass ssl_verify nossl_verify +ssl_cafile +ssl_capath +ssl_ciphers +ssl_fingerprint tls notls +tls_cert +tls_pkey +tls_pass tls_verify notls_verify +tls_cafile +tls_capath +tls_ciphers +tls_pinned_cert +tls_pinned_pubkey auto noauto proxy noproxy -host -port noautosendcmd"); signal_add("server looking", (SIGNAL_FUNC) sig_server_looking); signal_add("server connecting", (SIGNAL_FUNC) sig_server_connecting); diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index abbd45a8..de9f67a1 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -26,7 +26,7 @@ #include "misc.h" #include "lib-config/iconfig.h" #include "settings.h" - +#include "fe-settings.h" #include "levels.h" #include "printtext.h" #include "keyboard.h" @@ -41,6 +41,11 @@ static void set_print(SETTINGS_REC *rec) g_free(value); } +void fe_settings_set_print(const char *key) +{ + set_print(settings_get_record(key)); +} + static void set_print_pattern(const char *pattern) { GSList *sets, *tmp; diff --git a/src/fe-common/core/fe-settings.h b/src/fe-common/core/fe-settings.h new file mode 100644 index 00000000..dd33f223 --- /dev/null +++ b/src/fe-common/core/fe-settings.h @@ -0,0 +1,6 @@ +#ifndef __FE_CHANNELS_H +#define __FE_CHANNELS_H + +void fe_settings_set_print(const char *key); + +#endif diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c index 0afa2914..93f2e3f3 100644 --- a/src/fe-common/core/fe-windows.c +++ b/src/fe-common/core/fe-windows.c @@ -563,8 +563,10 @@ GSList *windows_get_sorted(void) begin = windows_seq_begin(); while (iter != begin) { + WINDOW_REC *rec; + iter = g_sequence_iter_prev(iter); - WINDOW_REC *rec = g_sequence_get(iter); + rec = g_sequence_get(iter); sorted = g_slist_prepend(sorted, rec); } diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index 17c13a97..37db6f7c 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -33,6 +33,7 @@ #include "themes.h" #include "recode.h" #include "utf8.h" +#include "misc.h" static const char *format_backs = "04261537"; static const char *format_fores = "kbgcrmyw"; @@ -870,8 +871,9 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, { static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; const char *start; - int fg, bg, flags, num, i; - unsigned int num2; + char *endptr; + int fg, bg, flags, i; + guint num, num2; if (*str != '[') return str; @@ -886,8 +888,10 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, if (*str == '\0') return start; if (i_isdigit(*str)) { - num = num*10 + (*str-'0'); - continue; + if (!parse_uint(str, &endptr, 10, &num)) { + return start; + } + str = endptr; } if (*str != ';' && *str != 'm') @@ -958,8 +962,12 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, /* ANSI indexed color or RGB color */ if (*str != ';') break; str++; - for (num2 = 0; i_isdigit(*str); str++) - num2 = num2*10 + (*str-'0'); + + if (!parse_uint(str, &endptr, 10, &num2)) { + return start; + } + str = endptr; + if (*str == '\0') return start; switch (num2) { @@ -1006,8 +1014,12 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, /* indexed */ if (*str != ';') break; str++; - for (num2 = 0; i_isdigit(*str); str++) - num2 = num2*10 + (*str-'0'); + + if (!parse_uint(str, &endptr, 10, &num2)) { + return start; + } + str = endptr; + if (*str == '\0') return start; if (num == 38) { @@ -1060,31 +1072,27 @@ static void get_mirc_color(const char **str, int *fg_ret, int *bg_ret) fg = fg_ret == NULL ? -1 : *fg_ret; bg = bg_ret == NULL ? -1 : *bg_ret; - if (!i_isdigit(**str) && **str != ',') { + if (!i_isdigit(**str)) { + /* turn off color */ fg = -1; bg = -1; } else { /* foreground color */ - if (**str != ',') { - fg = **str-'0'; + fg = **str-'0'; + (*str)++; + if (i_isdigit(**str)) { + fg = fg*10 + (**str-'0'); (*str)++; - if (i_isdigit(**str)) { - fg = fg*10 + (**str-'0'); - (*str)++; - } } - if (**str == ',') { + + if ((*str)[0] == ',' && i_isdigit((*str)[1])) { /* background color */ - if (!i_isdigit((*str)[1])) - bg = -1; - else { - (*str)++; - bg = **str-'0'; + (*str)++; + bg = **str-'0'; + (*str)++; + if (i_isdigit(**str)) { + bg = bg*10 + (**str-'0'); (*str)++; - if (i_isdigit(**str)) { - bg = bg*10 + (**str-'0'); - (*str)++; - } } } } diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index dd38be87..b9912457 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -26,6 +26,7 @@ #include "misc.h" #include "lib-config/iconfig.h" #include "settings.h" +#include "iregex.h" #include "servers.h" #include "channels.h" @@ -101,14 +102,11 @@ static void hilight_destroy(HILIGHT_REC *rec) { g_return_if_fail(rec != NULL); -#ifdef USE_GREGEX - if (rec->preg != NULL) g_regex_unref(rec->preg); -#else - if (rec->regexp_compiled) regfree(&rec->preg); -#endif + if (rec->preg != NULL) i_regex_unref(rec->preg); if (rec->channels != NULL) g_strfreev(rec->channels); g_free_not_null(rec->color); g_free_not_null(rec->act_color); + g_free_not_null(rec->servertag); g_free(rec->text); g_free(rec); } @@ -122,19 +120,10 @@ static void hilights_destroy_all(void) static void hilight_init_rec(HILIGHT_REC *rec) { -#ifdef USE_GREGEX if (rec->preg != NULL) - g_regex_unref(rec->preg); + i_regex_unref(rec->preg); - rec->preg = g_regex_new(rec->text, G_REGEX_OPTIMIZE | G_REGEX_RAW | G_REGEX_CASELESS, 0, NULL); -#else - if (rec->regexp_compiled) regfree(&rec->preg); - if (!rec->regexp) - rec->regexp_compiled = FALSE; - else - rec->regexp_compiled = regcomp(&rec->preg, rec->text, - rec->case_sensitive ? REG_EXTENDED : (REG_EXTENDED|REG_ICASE)) == 0; -#endif + rec->preg = i_regex_new(rec->text, G_REGEX_OPTIMIZE | G_REGEX_CASELESS, 0, NULL); } void hilight_create(HILIGHT_REC *rec) @@ -207,30 +196,15 @@ static gboolean hilight_match_text(HILIGHT_REC *rec, const char *text, gboolean ret = FALSE; if (rec->regexp) { -#ifdef USE_GREGEX if (rec->preg != NULL) { - GMatchInfo *match; - - g_regex_match (rec->preg, text, 0, &match); + MatchInfo *match; + i_regex_match(rec->preg, text, 0, &match); - if (g_match_info_matches(match)) - ret = g_match_info_fetch_pos(match, 0, match_beg, match_end); + if (i_match_info_matches(match)) + ret = i_match_info_fetch_pos(match, 0, match_beg, match_end); - g_match_info_free(match); - } -#else - regmatch_t rmatch[1]; - - if (rec->regexp_compiled && - regexec(&rec->preg, text, 1, rmatch, 0) == 0) { - if (rmatch[0].rm_so > 0 && - match_beg != NULL && match_end != NULL) { - *match_beg = rmatch[0].rm_so; - *match_end = rmatch[0].rm_eo; - } - ret = TRUE; + i_match_info_free(match); } -#endif } else { char *match; @@ -451,7 +425,7 @@ static void read_hilight_config(void) CONFIG_NODE *node; HILIGHT_REC *rec; GSList *tmp; - char *text, *color; + char *text, *color, *servertag; hilights_destroy_all(); @@ -494,7 +468,9 @@ static void read_hilight_config(void) rec->nickmask = config_node_get_bool(node, "mask", FALSE); rec->fullword = config_node_get_bool(node, "fullword", FALSE); rec->regexp = config_node_get_bool(node, "regexp", FALSE); - rec->servertag = config_node_get_str(node, "servertag", NULL); + servertag = config_node_get_str(node, "servertag", NULL); + rec->servertag = servertag == NULL || *servertag == '\0' ? NULL : + g_strdup(servertag); hilight_init_rec(rec); node = iconfig_node_section(node, "channels", -1); @@ -524,13 +500,8 @@ static void hilight_print(int index, HILIGHT_REC *rec) if (rec->case_sensitive) g_string_append(options, "-matchcase "); if (rec->regexp) { g_string_append(options, "-regexp "); -#ifdef USE_GREGEX if (rec->preg == NULL) g_string_append(options, "[INVALID!] "); -#else - if (!rec->regexp_compiled) - g_string_append(options, "[INVALID!] "); -#endif } if (rec->priority != 0) diff --git a/src/fe-common/core/hilight-text.h b/src/fe-common/core/hilight-text.h index 76beec1f..1d942f29 100644 --- a/src/fe-common/core/hilight-text.h +++ b/src/fe-common/core/hilight-text.h @@ -1,10 +1,7 @@ #ifndef __HILIGHT_TEXT_H #define __HILIGHT_TEXT_H -#ifndef USE_GREGEX -# include <regex.h> -#endif - +#include "iregex.h" #include "formats.h" struct _HILIGHT_REC { @@ -24,12 +21,7 @@ struct _HILIGHT_REC { unsigned int fullword:1; /* match `text' only for full words */ unsigned int regexp:1; /* `text' is a regular expression */ unsigned int case_sensitive:1;/* `text' must match case */ -#ifdef USE_GREGEX - GRegex *preg; -#else - unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ - regex_t preg; -#endif + Regex *preg; char *servertag; }; diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index da9705be..eb0ddb61 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -290,6 +290,9 @@ FORMAT_REC fecommon_core_formats[] = { { "completion_header", "%#Key Value Auto", 0 }, { "completion_line", "%#$[10]0 $[!40]1 $2", 3, { 0, 0, 0 } }, { "completion_footer", "", 0 }, + { "capsicum_enabled", "Capability mode enabled", 0 }, + { "capsicum_disabled", "Capability mode not enabled", 0 }, + { "capsicum_failed", "Capability mode failed: $0", 1, { 0 } }, /* ---- */ { NULL, "TLS", 0 }, diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h index a9ed28c5..97ac60bb 100644 --- a/src/fe-common/core/module-formats.h +++ b/src/fe-common/core/module-formats.h @@ -12,21 +12,21 @@ enum { TXT_DAYCHANGE, TXT_TALKING_WITH, TXT_REFNUM_TOO_LOW, - TXT_ERROR_SERVER_STICKY, - TXT_SET_SERVER_STICKY, + TXT_ERROR_SERVER_STICKY, + TXT_SET_SERVER_STICKY, TXT_UNSET_SERVER_STICKY, - TXT_WINDOW_NAME_NOT_UNIQUE, - TXT_WINDOW_LEVEL, - TXT_WINDOW_SET_IMMORTAL, - TXT_WINDOW_UNSET_IMMORTAL, - TXT_WINDOW_IMMORTAL_ERROR, + TXT_WINDOW_NAME_NOT_UNIQUE, + TXT_WINDOW_LEVEL, + TXT_WINDOW_SET_IMMORTAL, + TXT_WINDOW_UNSET_IMMORTAL, + TXT_WINDOW_IMMORTAL_ERROR, TXT_WINDOWLIST_HEADER, TXT_WINDOWLIST_LINE, TXT_WINDOWLIST_FOOTER, TXT_WINDOWS_LAYOUT_SAVED, TXT_WINDOWS_LAYOUT_RESET, - TXT_WINDOW_INFO_HEADER, - TXT_WINDOW_INFO_FOOTER, + TXT_WINDOW_INFO_HEADER, + TXT_WINDOW_INFO_FOOTER, TXT_WINDOW_INFO_REFNUM, TXT_WINDOW_INFO_REFNUM_STICKY, TXT_WINDOW_INFO_NAME, @@ -34,22 +34,22 @@ enum { TXT_WINDOW_INFO_IMMORTAL, TXT_WINDOW_INFO_SIZE, TXT_WINDOW_INFO_LEVEL, - TXT_WINDOW_INFO_SERVER, + TXT_WINDOW_INFO_SERVER, TXT_WINDOW_INFO_SERVER_STICKY, - TXT_WINDOW_INFO_THEME, + TXT_WINDOW_INFO_THEME, TXT_WINDOW_INFO_BOUND_ITEMS_HEADER, TXT_WINDOW_INFO_BOUND_ITEM, TXT_WINDOW_INFO_BOUND_ITEMS_FOOTER, TXT_WINDOW_INFO_ITEMS_HEADER, TXT_WINDOW_INFO_ITEM, - TXT_WINDOW_INFO_ITEMS_FOOTER, + TXT_WINDOW_INFO_ITEMS_FOOTER, TXT_FILL_2, TXT_LOOKING_UP, TXT_CONNECTING, - TXT_RECONNECTING, - TXT_CONNECTION_ESTABLISHED, + TXT_RECONNECTING, + TXT_CONNECTION_ESTABLISHED, TXT_CANT_CONNECT, TXT_CONNECTION_LOST, TXT_LAG_DISCONNECTED, @@ -100,7 +100,7 @@ enum { TXT_CHANSETUP_LINE, TXT_CHANSETUP_FOOTER, - TXT_FILL_4, + TXT_FILL_4, TXT_OWN_MSG, TXT_OWN_MSG_CHANNEL, @@ -162,7 +162,7 @@ enum { TXT_MODULE_HEADER, TXT_MODULE_LINE, - TXT_MODULE_FOOTER, + TXT_MODULE_FOOTER, TXT_MODULE_ALREADY_LOADED, TXT_MODULE_NOT_LOADED, TXT_MODULE_LOAD_ERROR, @@ -183,7 +183,7 @@ enum { TXT_NOT_JOINED, TXT_CHAN_NOT_FOUND, TXT_CHAN_NOT_SYNCED, - TXT_ILLEGAL_PROTO, + TXT_ILLEGAL_PROTO, TXT_NOT_GOOD_IDEA, TXT_INVALID_NUMBER, TXT_INVALID_TIME, @@ -232,8 +232,8 @@ enum { TXT_FILL_14, - TXT_UNKNOWN_CHAT_PROTOCOL, - TXT_UNKNOWN_CHATNET, + TXT_UNKNOWN_CHAT_PROTOCOL, + TXT_UNKNOWN_CHATNET, TXT_NOT_TOGGLE, TXT_PERL_ERROR, TXT_BIND_HEADER, @@ -245,16 +245,19 @@ enum { TXT_CONFIG_RELOADED, TXT_CONFIG_MODIFIED, TXT_GLIB_ERROR, - TXT_OVERWRITE_CONFIG, - TXT_SET_TITLE, - TXT_SET_ITEM, - TXT_SET_UNKNOWN, + TXT_OVERWRITE_CONFIG, + TXT_SET_TITLE, + TXT_SET_ITEM, + TXT_SET_UNKNOWN, TXT_SET_NOT_BOOLEAN, TXT_NO_COMPLETIONS, - TXT_COMPLETION_REMOVED, + TXT_COMPLETION_REMOVED, TXT_COMPLETION_HEADER, - TXT_COMPLETION_LINE, + TXT_COMPLETION_LINE, TXT_COMPLETION_FOOTER, + TXT_CAPSICUM_ENABLED, + TXT_CAPSICUM_DISABLED, + TXT_CAPSICUM_FAILED, TLS_FILL_15, diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c index 2b1459be..cb1cce8f 100644 --- a/src/fe-common/core/themes.c +++ b/src/fe-common/core/themes.c @@ -587,7 +587,7 @@ static char *theme_format_compress_colors(THEME_REC *theme, const char *format) /* a normal character */ g_string_append_c(str, *format); format++; - } else { + } else if (format[1] != '\0') { /* %format */ format++; if (IS_OLD_FORMAT(*format, last_fg, last_bg)) { @@ -614,6 +614,11 @@ static char *theme_format_compress_colors(THEME_REC *theme, const char *format) last_bg = '\0'; } format++; + } else { + /* % at end of string */ + format++; + g_string_append_c(str, '%'); + g_string_append_c(str, '%'); } } |