1 Commits

Author SHA1 Message Date
e49333340f Tighten Flatpak perms, pin lgi source 2026-04-12 23:43:12 -06:00
11 changed files with 15 additions and 371 deletions

View File

@@ -7,14 +7,13 @@
"command": "zoitechat", "command": "zoitechat",
"finish-args": [ "finish-args": [
"--share=ipc", "--share=ipc",
"--socket=x11", "--socket=wayland",
"--socket=fallback-x11",
"--share=network", "--share=network",
"--socket=pulseaudio", "--socket=pulseaudio",
"--filesystem=xdg-download", "--filesystem=xdg-download",
"--filesystem=xdg-data/themes:ro", "--filesystem=xdg-data/themes:ro",
"--filesystem=xdg-data/icons:ro", "--filesystem=xdg-data/icons:ro",
"--filesystem=~/.themes:ro",
"--filesystem=~/.icons:ro",
"--filesystem=xdg-run/tray-icon:create", "--filesystem=xdg-run/tray-icon:create",
"--env=GTK_CSD=1", "--env=GTK_CSD=1",
"--talk-name=org.freedesktop.Notifications", "--talk-name=org.freedesktop.Notifications",
@@ -45,9 +44,9 @@
"buildsystem": "meson", "buildsystem": "meson",
"sources": [ "sources": [
{ {
"type": "git", "type": "archive",
"url": "https://github.com/pavouk/lgi.git", "url": "https://github.com/pavouk/lgi/archive/c9b8e4473c6421f2a215d8c06c0d94b86eb0b26a.tar.gz",
"commit": "c9b8e4473c6421f2a215d8c06c0d94b86eb0b26a" "sha256": "db67b2b7ee89fa566f783486d56be7203552a997bc55f35020b57dd2776b9943"
} }
] ]
}, },

View File

@@ -29,7 +29,6 @@
<ClInclude Include="plugin-timer.h" /> <ClInclude Include="plugin-timer.h" />
<ClInclude Include="plugin.h" /> <ClInclude Include="plugin.h" />
<ClInclude Include="proto-irc.h" /> <ClInclude Include="proto-irc.h" />
<ClInclude Include="public_suffix_data.h" />
<ClInclude Include="server.h" /> <ClInclude Include="server.h" />
<ClInclude Include="servlist.h" /> <ClInclude Include="servlist.h" />
<ClInclude Include="ssl.h" /> <ClInclude Include="ssl.h" />
@@ -110,7 +109,6 @@
<Command><![CDATA[ <Command><![CDATA[
SET SOLUTIONDIR=$(SolutionDir)..\ SET SOLUTIONDIR=$(SolutionDir)..\
"$(Python3Path)\python.exe" $(ProjectDir)make-te.py "$(ProjectDir)textevents.in" "$(ZoiteChatLib)textevents.h" "$(ZoiteChatLib)textenums.h" "$(Python3Path)\python.exe" $(ProjectDir)make-te.py "$(ProjectDir)textevents.in" "$(ZoiteChatLib)textevents.h" "$(ZoiteChatLib)textenums.h"
"$(Python3Path)\python.exe" $(ProjectDir)gen-public-suffix.py "$(ZoiteChatLib)public_suffix_data.h"
powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\win32\config.h.tt" "$(ZoiteChatLib)config.h" powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\win32\config.h.tt" "$(ZoiteChatLib)config.h"
$(GlibGenMarshal) --prefix=_zoitechat_marshal --header "$(ProjectDir)marshalers.list" --output "$(ZoiteChatLib)marshal.h" $(GlibGenMarshal) --prefix=_zoitechat_marshal --header "$(ProjectDir)marshalers.list" --output "$(ZoiteChatLib)marshal.h"
$(GlibGenMarshal) --prefix=_zoitechat_marshal --body "$(ProjectDir)marshalers.list" --output "$(ZoiteChatLib)marshal.c" $(GlibGenMarshal) --prefix=_zoitechat_marshal --body "$(ProjectDir)marshalers.list" --output "$(ZoiteChatLib)marshal.c"

View File

@@ -65,9 +65,6 @@
<ClInclude Include="proto-irc.h"> <ClInclude Include="proto-irc.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="public_suffix_data.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="server.h"> <ClInclude Include="server.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -1,71 +0,0 @@
#!/usr/bin/env python3
import sys
import urllib.request
from pathlib import Path
URLS = (
"https://raw.githubusercontent.com/publicsuffix/list/main/public_suffix_list.dat",
"https://publicsuffix.org/list/public_suffix_list.dat",
)
def parse_rules(text: str):
rules = []
for raw in text.splitlines():
line = raw.strip()
if not line or line.startswith("//"):
continue
if " " in line or "\t" in line:
line = line.split()[0]
rules.append(line.lower())
return sorted(set(rules))
def emit_header(path: str, rules):
with open(path, "w", encoding="utf-8", newline="\n") as out:
out.write("#pragma once\n")
out.write("static const char * const public_suffix_rules[] = {\n")
for rule in rules:
escaped = rule.replace("\\", "\\\\").replace('"', '\\"')
out.write(f'\t"{escaped}",\n')
out.write("};\n")
out.write(
"static const unsigned int public_suffix_rules_len = sizeof(public_suffix_rules) / sizeof(public_suffix_rules[0]);\n"
)
def main():
if len(sys.argv) not in (2, 3):
raise SystemExit("usage: gen-public-suffix.py <output> [source]")
output = Path(sys.argv[1])
sources = []
if len(sys.argv) == 3:
sources.append(Path(sys.argv[2]))
sources.extend(
[
Path(__file__).with_name("public_suffix_list.dat"),
Path("/usr/share/publicsuffix/public_suffix_list.dat"),
Path("/app/share/publicsuffix/public_suffix_list.dat"),
]
)
data = None
for url in URLS:
try:
with urllib.request.urlopen(url, timeout=30) as resp:
data = resp.read().decode("utf-8")
break
except Exception:
pass
if data is None:
for source in sources:
if source.exists():
data = source.read_text(encoding="utf-8")
break
if data is None:
raise SystemExit("unable to load public suffix list")
rules = parse_rules(data)
emit_header(str(output), rules)
if __name__ == "__main__":
main()

View File

@@ -96,15 +96,6 @@ marshal = [
make_te = find_program('make-te.py') make_te = find_program('make-te.py')
python3 = find_program('python3', required: true)
public_suffix_data = custom_target('public_suffix_data_h',
input: 'public_suffix_list.dat',
output: 'public_suffix_data.h',
command: [python3, files('gen-public-suffix.py'), '@OUTPUT@', '@INPUT@']
)
textevents = custom_target('textevents', textevents = custom_target('textevents',
input: 'textevents.in', input: 'textevents.in',
output: ['textevents.h', 'textenums.h'], output: ['textevents.h', 'textenums.h'],
@@ -128,7 +119,7 @@ if get_option('plugin')
endif endif
zoitechat_common = static_library('zoitechatcommon', zoitechat_common = static_library('zoitechatcommon',
sources: [textevents, public_suffix_data] + marshal + common_sources, sources: [textevents] + marshal + common_sources,
include_directories: config_h_include, include_directories: config_h_include,
dependencies: common_deps + common_sysinfo_deps, dependencies: common_deps + common_sysinfo_deps,
c_args: common_cflags, c_args: common_cflags,
@@ -136,7 +127,7 @@ zoitechat_common = static_library('zoitechatcommon',
) )
zoitechat_common_dep = declare_dependency( zoitechat_common_dep = declare_dependency(
sources: [textevents, public_suffix_data] + marshal, sources: [textevents] + marshal,
link_with: zoitechat_common, link_with: zoitechat_common,
include_directories: common_includes, include_directories: common_includes,
compile_args: common_cflags, compile_args: common_cflags,

View File

@@ -20,14 +20,12 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <glib.h>
#include "zoitechat.h" #include "zoitechat.h"
#include "zoitechatc.h" #include "zoitechatc.h"
#include "cfgfiles.h" #include "cfgfiles.h"
#include "fe.h" #include "fe.h"
#include "tree.h" #include "tree.h"
#include "url.h" #include "url.h"
#include "public_suffix_data.h"
#ifdef HAVE_STRINGS_H #ifdef HAVE_STRINGS_H
#include <strings.h> #include <strings.h>
#endif #endif
@@ -37,7 +35,6 @@ GTree *url_btree = NULL;
static gboolean regex_match (const GRegex *re, const char *word, static gboolean regex_match (const GRegex *re, const char *word,
int *start, int *end); int *start, int *end);
static const GRegex *re_url (void); static const GRegex *re_url (void);
static const GRegex *re_url_no_scheme (void);
static const GRegex *re_email (void); static const GRegex *re_email (void);
static const GRegex *re_nick (void); static const GRegex *re_nick (void);
static const GRegex *re_channel (void); static const GRegex *re_channel (void);
@@ -45,8 +42,6 @@ static gboolean match_nick (const char *word, int *start, int *end);
static gboolean match_channel (const char *word, int *start, int *end); static gboolean match_channel (const char *word, int *start, int *end);
static gboolean match_url (const char *word, int *start, int *end); static gboolean match_url (const char *word, int *start, int *end);
static gboolean match_email (const char *word, int *start, int *end); static gboolean match_email (const char *word, int *start, int *end);
static gboolean host_has_public_suffix (const char *host);
static gboolean host_has_public_suffix_range (const char *word, int start, int end);
static int static int
url_free (char *url, void *data) url_free (char *url, void *data)
@@ -271,16 +266,7 @@ match_channel (const char *word, int *start, int *end)
static gboolean static gboolean
match_url (const char *word, int *start, int *end) match_url (const char *word, int *start, int *end)
{ {
if (regex_match (re_url (), word, start, end)) return regex_match (re_url (), word, start, end);
return TRUE;
if (!regex_match (re_url_no_scheme (), word, start, end))
return FALSE;
if (*start > 0 && word[*start - 1] == '@')
return FALSE;
return host_has_public_suffix_range (word, *start, *end);
} }
static gboolean static gboolean
@@ -407,114 +393,6 @@ regex_match (const GRegex *re, const char *word, int *start, int *end)
return found; return found;
} }
static gboolean
host_has_public_suffix_range (const char *word, int start, int end)
{
char *candidate;
const char *host_start;
const char *host_end;
const char *host_colon;
gboolean ok;
int host_len;
char *host;
candidate = g_strndup (word + start, end - start);
host_start = candidate;
host_end = candidate + strlen (candidate);
if (*host_start == '[')
{
g_free (candidate);
return FALSE;
}
host_colon = strchr (host_start, ':');
if (host_colon)
host_end = host_colon;
host_colon = strchr (host_start, '/');
if (host_colon && host_colon < host_end)
host_end = host_colon;
host_len = (int)(host_end - host_start);
if (host_len <= 0)
{
g_free (candidate);
return FALSE;
}
host = g_strndup (host_start, host_len);
ok = host_has_public_suffix (host);
g_free (host);
g_free (candidate);
return ok;
}
static GHashTable *
public_suffix_table (void)
{
static GHashTable *table = NULL;
unsigned int i;
if (table)
return table;
table = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0; i < public_suffix_rules_len; i++)
{
g_hash_table_add (table, (gpointer)public_suffix_rules[i]);
}
return table;
}
static gboolean
host_has_public_suffix (const char *host)
{
GHashTable *table;
gchar **labels;
int i;
int n;
gboolean matched = FALSE;
if (!strchr (host, '.'))
return FALSE;
labels = g_strsplit (host, ".", -1);
for (n = 0; labels[n]; n++)
{
if (labels[n][0] == '\0')
{
g_strfreev (labels);
return FALSE;
}
}
table = public_suffix_table ();
for (i = 0; i < n; i++)
{
char *tail = g_strjoinv (".", &labels[i]);
if (g_hash_table_contains (table, tail))
matched = TRUE;
if (i + 1 < n)
{
char *tail_wild = g_strjoinv (".", &labels[i + 1]);
char *wild = g_strconcat ("*.", tail_wild, NULL);
if (g_hash_table_contains (table, wild))
matched = TRUE;
g_free (tail_wild);
g_free (wild);
}
if (i > 0)
{
char *exc = g_strconcat ("!", tail, NULL);
if (g_hash_table_contains (table, exc))
matched = TRUE;
g_free (exc);
}
g_free (tail);
if (matched)
break;
}
g_strfreev (labels);
return matched;
}
/* Miscellaneous description --- */ /* Miscellaneous description --- */
#define DOMAIN_LABEL "[\\pL\\pN](?:[-\\pL\\pN]{0,61}[\\pL\\pN])?" #define DOMAIN_LABEL "[\\pL\\pN](?:[-\\pL\\pN]{0,61}[\\pL\\pN])?"
#define DOMAIN DOMAIN_LABEL "(\\." DOMAIN_LABEL ")*" #define DOMAIN DOMAIN_LABEL "(\\." DOMAIN_LABEL ")*"
@@ -599,28 +477,6 @@ re_url (void)
return url_ret; return url_ret;
} }
static const GRegex *
re_url_no_scheme (void)
{
static GRegex *url_ret = NULL;
GString *grist_gstr;
char *grist;
if (url_ret) return url_ret;
grist_gstr = g_string_new (NULL);
g_string_append (grist_gstr, "(");
g_string_append (grist_gstr, HOST_URL_OPT_TLD OPT_PORT);
g_string_append_printf (grist_gstr, "(/" PATH ")?");
g_string_append (grist_gstr, ")");
grist = g_string_free (grist_gstr, FALSE);
url_ret = make_re (grist);
g_free (grist);
return url_ret;
}
#define EMAIL_LOCAL_ATOM "[\\pL\\pN!#$%&'*+/=?^_`{|}~-]+" #define EMAIL_LOCAL_ATOM "[\\pL\\pN!#$%&'*+/=?^_`{|}~-]+"
#define EMAIL_LOCAL EMAIL_LOCAL_ATOM "(\\." EMAIL_LOCAL_ATOM ")*" #define EMAIL_LOCAL EMAIL_LOCAL_ATOM "(\\." EMAIL_LOCAL_ATOM ")*"
#define EMAIL EMAIL_LOCAL "@" DOMAIN TLD #define EMAIL EMAIL_LOCAL "@" DOMAIN TLD

View File

@@ -45,8 +45,6 @@ cv_tree_sel_cb (GtkTreeSelection *sel, chanview *cv)
GtkTreeModel *model; GtkTreeModel *model;
GtkTreeIter prev_iter; GtkTreeIter prev_iter;
GtkTreeIter iter; GtkTreeIter iter;
GtkTreePath *path;
GtkTreeView *view;
chan *ch; chan *ch;
chan *prev_ch; chan *prev_ch;
gboolean has_prev; gboolean has_prev;
@@ -62,20 +60,6 @@ cv_tree_sel_cb (GtkTreeSelection *sel, chanview *cv)
if (has_prev) if (has_prev)
{ {
gtk_tree_model_get (model, &prev_iter, COL_CHAN, &prev_ch, -1); gtk_tree_model_get (model, &prev_iter, COL_CHAN, &prev_ch, -1);
if (prev_ch != ch && gtk_tree_store_is_ancestor (cv->store, &iter, &prev_iter))
{
view = gtk_tree_selection_get_tree_view (sel);
path = gtk_tree_model_get_path (model, &iter);
if (path)
{
if (!gtk_tree_view_row_expanded (view, path))
{
gtk_tree_path_free (path);
return;
}
gtk_tree_path_free (path);
}
}
if (prev_ch != ch) if (prev_ch != ch)
gtk_tree_store_set (cv->store, &prev_iter, COL_UNDERLINE, PANGO_UNDERLINE_NONE, -1); gtk_tree_store_set (cv->store, &prev_iter, COL_UNDERLINE, PANGO_UNDERLINE_NONE, -1);
} }

View File

@@ -443,27 +443,6 @@ key_handle_key_press (GtkWidget *wid, GdkEventKey *evt, session *sess)
if (!list) if (!list)
return FALSE; return FALSE;
current_sess = sess; current_sess = sess;
if ((evt->state & GDK_CONTROL_MASK) &&
!(evt->state & (GDK_MOD1_MASK | GDK_META_MASK)))
{
if (!(evt->state & GDK_SHIFT_MASK) &&
(evt->keyval == GDK_KEY_w || evt->keyval == GDK_KEY_W))
{
if (sess->type == SESS_CHANNEL)
{
fe_close_window (sess);
g_signal_stop_emission_by_name (G_OBJECT (wid), "key-press-event");
return 1;
}
}
if ((evt->state & GDK_SHIFT_MASK) &&
(evt->keyval == GDK_KEY_t || evt->keyval == GDK_KEY_T))
{
mg_reopen_closed_channel_tab ();
g_signal_stop_emission_by_name (G_OBJECT (wid), "key-press-event");
return 1;
}
}
if (plugin_emit_keypress (sess, evt->state, evt->keyval, gdk_keyval_to_unicode (evt->keyval))) if (plugin_emit_keypress (sess, evt->state, evt->keyval, gdk_keyval_to_unicode (evt->keyval)))
return 1; return 1;

View File

@@ -468,14 +468,6 @@ static session_gui static_mg_gui;
static session_gui *mg_gui = NULL; /* the shared irc tab */ static session_gui *mg_gui = NULL; /* the shared irc tab */
static int ignore_chanmode = FALSE; static int ignore_chanmode = FALSE;
static const char chan_flags[] = { 'c', 'n', 't', 'i', 'm', 'l', 'k' }; static const char chan_flags[] = { 'c', 'n', 't', 'i', 'm', 'l', 'k' };
typedef struct
{
int server_id;
char channel[CHANLEN];
char key[64];
}
mg_closed_channel_tab;
static GSList *mg_closed_channel_tabs;
static chan *active_tab = NULL; /* active tab */ static chan *active_tab = NULL; /* active tab */
GtkWidget *parent_window = NULL; /* the master window */ GtkWidget *parent_window = NULL; /* the master window */
@@ -1651,71 +1643,6 @@ mg_tab_close_cb (GtkWidget *dialog, gint arg1, session *sess)
} }
} }
static void
mg_closed_channel_tabs_add (session *sess)
{
mg_closed_channel_tab *item;
GSList *last;
if (!sess || sess->type != SESS_CHANNEL || !sess->channel[0])
return;
item = g_new0 (mg_closed_channel_tab, 1);
item->server_id = sess->server->id;
g_strlcpy (item->channel, sess->channel, sizeof (item->channel));
g_strlcpy (item->key, sess->channelkey, sizeof (item->key));
mg_closed_channel_tabs = g_slist_prepend (mg_closed_channel_tabs, item);
if (g_slist_length (mg_closed_channel_tabs) > 20)
{
last = g_slist_last (mg_closed_channel_tabs);
g_free (last->data);
mg_closed_channel_tabs = g_slist_delete_link (mg_closed_channel_tabs, last);
}
}
void
mg_reopen_closed_channel_tab (void)
{
mg_closed_channel_tab *item;
GSList *head;
GSList *list;
server *serv;
session *sess;
if (!mg_closed_channel_tabs)
return;
head = mg_closed_channel_tabs;
item = head->data;
mg_closed_channel_tabs = g_slist_delete_link (mg_closed_channel_tabs, head);
if (!item)
return;
serv = NULL;
for (list = serv_list; list; list = list->next)
{
server *candidate = list->data;
if (candidate->id == item->server_id)
{
serv = candidate;
break;
}
}
if (serv && serv->connected && item->channel[0])
{
sess = find_channel (serv, item->channel);
if (sess)
fe_ctrl_gui (sess, 2, 0);
else
{
new_ircwindow (serv, item->channel, SESS_CHANNEL, 1);
serv->p_join (serv, item->channel, item->key);
}
}
g_free (item);
}
void void
mg_tab_close (session *sess) mg_tab_close (session *sess)
{ {
@@ -1723,12 +1650,11 @@ mg_tab_close (session *sess)
GSList *list; GSList *list;
int i; int i;
if (chan_remove (sess->res->tab, FALSE)) if (chan_remove (sess->res->tab, FALSE))
{ {
mg_closed_channel_tabs_add (sess); sess->res->tab = NULL;
sess->res->tab = NULL; mg_ircdestroy (sess);
mg_ircdestroy (sess); }
}
else else
{ {
for (i = 0, list = sess_list; list; list = list->next) for (i = 0, list = sess_list; list; list = list->next)
@@ -2571,7 +2497,6 @@ mg_topic_word_is_clickable (const char *word, int word_pos)
{ {
int start; int start;
int end; int end;
int word_type;
if (!word || word[0] == 0) if (!word || word[0] == 0)
return FALSE; return FALSE;
@@ -2579,8 +2504,7 @@ mg_topic_word_is_clickable (const char *word, int word_pos)
if (strcmp (word, "/") == 0) if (strcmp (word, "/") == 0)
return FALSE; return FALSE;
word_type = url_check_word (word); if (url_check_word (word) == 0)
if (word_type != WORD_URL && word_type != WORD_HOST && word_type != WORD_HOST6)
return FALSE; return FALSE;
url_last (&start, &end); url_last (&start, &end);
@@ -2629,8 +2553,7 @@ mg_topic_button_release_cb (GtkWidget *entry, GdkEventButton *event, gpointer us
if (!word) if (!word)
return FALSE; return FALSE;
if ((event->state & 13) == prefs.hex_gui_url_mod && if (mg_topic_word_is_clickable (word, word_pos))
mg_topic_word_is_clickable (word, word_pos))
{ {
url_last (&start, &end); url_last (&start, &end);
word[end] = 0; word[end] = 0;

View File

@@ -40,7 +40,6 @@ void mg_apply_setup (void);
void mg_apply_session_font_prefs (session_gui *gui); void mg_apply_session_font_prefs (session_gui *gui);
void mg_close_sess (session *); void mg_close_sess (session *);
void mg_tab_close (session *sess); void mg_tab_close (session *sess);
void mg_reopen_closed_channel_tab (void);
void mg_detach (session *sess, int mode); void mg_detach (session *sess, int mode);
void mg_progressbar_create (session_gui *gui); void mg_progressbar_create (session_gui *gui);
void mg_progressbar_destroy (session_gui *gui); void mg_progressbar_destroy (session_gui *gui);

View File

@@ -59,17 +59,6 @@ fe_open_url (const char *url)
(void)url; (void)url;
} }
char *
get_xdir (void)
{
return (char *)"/tmp";
}
void
load_text_events (void)
{
}
gboolean gboolean
theme_get_color (ThemeSemanticToken token, GdkRGBA *color) theme_get_color (ThemeSemanticToken token, GdkRGBA *color)
{ {