[Commits] [SCM] claws branch, master, updated. 4.3.1-50-g24a7d15ed

wwp at claws-mail.org wwp at claws-mail.org
Fri Mar 21 10:17:05 UTC 2025


The branch, master has been updated
       via  24a7d15ed475beb0483874974739f3b1163542cb (commit)
      from  803450e8a64324eb0767fe69411a2518426f3e8d (commit)

Summary of changes:
 src/plugins/rssyl/libfeed/feed.c          | 19 +++++----
 src/plugins/rssyl/libfeed/feed.h          |  4 +-
 src/plugins/rssyl/rssyl.c                 | 24 ++++++++++-
 src/plugins/rssyl/rssyl.h                 |  6 ++-
 src/plugins/rssyl/rssyl_feed.h            |  4 +-
 src/plugins/rssyl/rssyl_feed_props.c      | 59 ++++++++++++++++++++++++--
 src/plugins/rssyl/rssyl_feed_props.h      |  4 +-
 src/plugins/rssyl/rssyl_prefs.c           | 70 +++++++++++++++++++++++++++++--
 src/plugins/rssyl/rssyl_prefs.h           | 15 ++-----
 src/plugins/rssyl/rssyl_update_comments.c |  5 ++-
 src/plugins/rssyl/rssyl_update_feed.c     | 58 +++++++++++++++++++++++--
 11 files changed, 230 insertions(+), 38 deletions(-)


- Log -----------------------------------------------------------------
commit 24a7d15ed475beb0483874974739f3b1163542cb
Author: wwp <subscript at free.fr>
Date:   Fri Mar 21 11:15:09 2025 +0100

    RSSyl plugin: change the default User Agent used to retrieve feeds to ClawsMailRSSyl/$VERSION ($URL),
    allow users to make use of a custom User Agent (in preferences) to override the default one,
    allow users to override the User Agent on a per-feed basis as well.

diff --git a/src/plugins/rssyl/libfeed/feed.c b/src/plugins/rssyl/libfeed/feed.c
index 8c135b6bc..29b0bb26d 100644
--- a/src/plugins/rssyl/libfeed/feed.c
+++ b/src/plugins/rssyl/libfeed/feed.c
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2006-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2006-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -24,6 +24,7 @@
 #include <expat.h>
 
 #include "feed.h"
+#include "../rssyl_prefs.h"
 #include "parser.h"
 
 /* feed_new()
@@ -68,13 +69,13 @@ static void _free_auth(Feed *feed)
 		return;
 
 	if (feed->auth != NULL) {
-                if (feed->auth->username != NULL)
-                        g_free(feed->auth->username);
-                if (feed->auth->password != NULL)
-                        g_free(feed->auth->password);
-                g_free(feed->auth);
+		if (feed->auth->username != NULL)
+			g_free(feed->auth->username);
+		if (feed->auth->password != NULL)
+			g_free(feed->auth->password);
+		g_free(feed->auth);
 		feed->auth = NULL;
-        }
+	}
 }
 
 void feed_free(Feed *feed)
@@ -245,7 +246,7 @@ FeedItem *feed_nth_item(Feed *feed, guint n)
  * Takes initialized feed with url set, fetches the feed from this url,
  * updates rest of Feed struct members and returns HTTP response code
  * we got from url's server. */
-guint feed_update(Feed *feed, time_t last_update)
+guint feed_update(Feed *feed, time_t last_update, const gchar *user_agent)
 {
 	CURL *eh = NULL;
 	CURLcode res;
@@ -291,7 +292,7 @@ guint feed_update(Feed *feed, time_t last_update)
 	curl_easy_setopt(eh, CURLOPT_TIMEOUT, feed->timeout);
 	curl_easy_setopt(eh, CURLOPT_NOSIGNAL, 1);
 	curl_easy_setopt(eh, CURLOPT_ENCODING, "");
-	curl_easy_setopt(eh, CURLOPT_USERAGENT, "libfeed 0.1");
+	curl_easy_setopt(eh, CURLOPT_USERAGENT, user_agent);
 	curl_easy_setopt(eh, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
 
 	/* Use HTTP's If-Modified-Since feature, if application provided
diff --git a/src/plugins/rssyl/libfeed/feed.h b/src/plugins/rssyl/libfeed/feed.h
index 0b4126cb7..46e95094a 100644
--- a/src/plugins/rssyl/libfeed/feed.h
+++ b/src/plugins/rssyl/libfeed/feed.h
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2006-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2006-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -129,7 +129,7 @@ gboolean feed_prepend_item(Feed *feed, FeedItem *item);
 gboolean feed_append_item(Feed *feed, FeedItem *item);
 gboolean feed_insert_item(Feed *feed, FeedItem *item, gint pos);
 
-guint feed_update(Feed *feed, time_t last_update);
+guint feed_update(Feed *feed, time_t last_update, const gchar *user_agent);
 
 #define FILL(n)		do { g_free(n); n = g_strdup(text); } while(0);
 
diff --git a/src/plugins/rssyl/rssyl.c b/src/plugins/rssyl/rssyl.c
index 604cee0bd..b85a8f6d9 100644
--- a/src/plugins/rssyl/rssyl.c
+++ b/src/plugins/rssyl/rssyl.c
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2005-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2005-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -324,6 +324,13 @@ static void rssyl_item_set_xml(Folder *folder, FolderItem *item, XMLTag *tag)
 		/* (bool) Verify SSL peer  */
 		if( !strcmp(attr->name, "ssl_verify_peer"))
 			ritem->ssl_verify_peer = (atoi(attr->value) == 0 ? FALSE : TRUE );
+		/* User Agent */
+		if( !strcmp(attr->name, "use_default_user_agent"))
+			ritem->use_default_user_agent = (atoi(attr->value) == 0 ? FALSE : TRUE );
+		if( !strcmp(attr->name, "specific_user_agent")) {
+			g_free(ritem->specific_user_agent);
+			ritem->specific_user_agent = g_strdup(attr->value);
+		}
 	}
 }
 
@@ -378,6 +385,11 @@ static XMLTag *rssyl_item_get_xml(Folder *folder, FolderItem *item)
 	/* (bool) Verify SSL peer */
 	xml_tag_add_attr(tag, xml_attr_new("ssl_verify_peer",
 				(ri->ssl_verify_peer ? "1" : "0")) );
+	/* User Agent */
+	xml_tag_add_attr(tag, xml_attr_new("use_default_user_agent",
+				(ri->use_default_user_agent ? "1" : "0")) );
+	if( ri->specific_user_agent != NULL )
+		xml_tag_add_attr(tag, xml_attr_new("specific_user_agent", ri->specific_user_agent));
 
 	return tag;
 }
@@ -444,6 +456,8 @@ static FolderItem *rssyl_item_new(Folder *folder)
 	ritem->ssl_verify_peer = TRUE;
 	ritem->feedprop = NULL;
 	ritem->refresh_id = 0;
+	ritem->use_default_user_agent = 1;
+	ritem->specific_user_agent = NULL;
 
 	return (FolderItem *)ritem;
 }
@@ -462,6 +476,7 @@ static void rssyl_item_destroy(Folder *folder, FolderItem *item)
 	g_free(ritem->auth);
 	g_free(ritem->official_title);
 	g_slist_free(ritem->items);
+	g_free(ritem->specific_user_agent);
 
 	/* Remove a scheduled refresh, if any */
 	if( ritem->refresh_id != 0)
@@ -980,6 +995,13 @@ static void rssyl_copy_private_data(Folder *folder, FolderItem *oldi,
 	newitem->fetching_comments = olditem->fetching_comments;
 	newitem->last_update = olditem->last_update;
 
+	/* User Agent */
+	newitem->use_default_user_agent = olditem->use_default_user_agent;
+	if (olditem->specific_user_agent != NULL) {
+		g_free(newitem->specific_user_agent);
+		newitem->specific_user_agent = g_strdup(olditem->specific_user_agent);
+	}
+
 	pathold = rssyl_item_get_path(oldi->folder, oldi);
 	dpathold = g_strconcat(pathold, G_DIR_SEPARATOR_S, RSSYL_DELETED_FILE, NULL);
 	pathnew = rssyl_item_get_path(newi->folder, newi);
diff --git a/src/plugins/rssyl/rssyl.h b/src/plugins/rssyl/rssyl.h
index 2519c0d51..31952817a 100644
--- a/src/plugins/rssyl/rssyl.h
+++ b/src/plugins/rssyl/rssyl.h
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2005-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2005-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -67,6 +67,9 @@ struct _RFolderItem {
 	gboolean fetching_comments;
 	time_t last_update;
 
+	gboolean use_default_user_agent;
+	gchar *specific_user_agent;
+
 	struct _RFeedProp *feedprop;
 
 	GSList *items;
@@ -88,6 +91,7 @@ struct _RFetchCtx {
 	gchar *error;
 	gboolean success;
 	gboolean ready;
+	RFolderItem *ritem;
 };
 
 typedef struct _RFetchCtx RFetchCtx;
diff --git a/src/plugins/rssyl/rssyl_feed.h b/src/plugins/rssyl/rssyl_feed.h
index 36749bede..4987c9ece 100644
--- a/src/plugins/rssyl/rssyl_feed.h
+++ b/src/plugins/rssyl/rssyl_feed.h
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2005-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2005-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -27,7 +27,7 @@
 
 #define RSSYL_LOG_SUBSCRIBING  _("RSSyl: Subscribing new feed: %s\n")
 #define RSSYL_LOG_SUBSCRIBED   _("RSSyl: New feed subscribed: '%s' (%s)\n")
-#define RSSYL_LOG_UPDATING     _("RSSyl: Updating feed: %s\n")
+#define RSSYL_LOG_UPDATING     _("RSSyl: Updating feed: %s (User Agent: %s)\n")
 #define RSSYL_LOG_UPDATED      _("RSSyl: Feed update finished: %s\n")
 #define RSSYL_LOG_ERROR_FETCH  _("RSSyl: Error fetching feed at '%s': %s\n")
 #define RSSYL_LOG_ERROR_NOFEED _("RSSyl: No valid feed found at '%s'\n")
diff --git a/src/plugins/rssyl/rssyl_feed_props.c b/src/plugins/rssyl/rssyl_feed_props.c
index 795a15869..44bb6f4fa 100644
--- a/src/plugins/rssyl/rssyl_feed_props.c
+++ b/src/plugins/rssyl/rssyl_feed_props.c
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2005-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2005-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -40,9 +40,9 @@
 
 static void rssyl_gtk_prop_store(RFolderItem *ritem)
 {
-	gchar *url, *auth_user, *auth_pass;
+	gchar *url, *auth_user, *auth_pass, *specific_user_agent;
 	gint x, old_ri, old_fetch_comments;
-	gboolean use_default_ri = FALSE, keep_old = FALSE;
+	gboolean use_default_ri = FALSE, keep_old = FALSE, use_default_user_agent = TRUE;
 	FolderItem *item;
 
 	g_return_if_fail(ritem != NULL);
@@ -125,6 +125,21 @@ static void rssyl_gtk_prop_store(RFolderItem *ritem)
 	ritem->ssl_verify_peer = gtk_toggle_button_get_active(
 			GTK_TOGGLE_BUTTON(ritem->feedprop->ssl_verify_peer));
 
+	/* User Agent */
+	use_default_user_agent = gtk_toggle_button_get_active(
+			GTK_TOGGLE_BUTTON(ritem->feedprop->use_default_user_agent));
+	ritem->use_default_user_agent = use_default_user_agent;
+	debug_print("store: use default user agent is %s\n",
+			( use_default_user_agent ? "ON" : "OFF" ) );
+
+	specific_user_agent = (gchar *)gtk_entry_get_text(GTK_ENTRY(ritem->feedprop->specific_user_agent));
+	if (specific_user_agent != NULL) {
+		if (ritem->specific_user_agent) {
+			g_free(ritem->specific_user_agent);
+		}
+		ritem->specific_user_agent = g_strdup(specific_user_agent);
+	}
+
 	/* Store updated properties */
 	item = &ritem->item;
 	item->folder->klass->item_get_xml(item->folder, item);
@@ -143,6 +158,9 @@ rssyl_feedprop_togglebutton_toggled_cb(GtkToggleButton *tb,
 		sb = feedprop->refresh_interval;
 	} else if( (GtkWidget *)tb == feedprop->fetch_comments ) {
 		sb = feedprop->fetch_comments_max_age;
+	} else if((GtkWidget *)tb == feedprop->use_default_user_agent ) {
+		active = !active;
+		sb = feedprop->specific_user_agent;
 	}
 
 	g_return_val_if_fail(sb != NULL, FALSE);
@@ -356,6 +374,17 @@ void rssyl_gtk_prop(RFolderItem *ritem)
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(feedprop->ssl_verify_peer),
 			ritem->ssl_verify_peer);
 
+	/* User Agent */
+	feedprop->use_default_user_agent = gtk_check_button_new_with_mnemonic(
+			_("Use default User Agent"));
+	gtk_toggle_button_set_active(
+			GTK_TOGGLE_BUTTON(feedprop->use_default_user_agent),
+			ritem->use_default_user_agent);
+
+	feedprop->specific_user_agent = gtk_entry_new();
+	gtk_entry_set_text(GTK_ENTRY(feedprop->specific_user_agent),
+			(ritem->specific_user_agent != NULL ? ritem->specific_user_agent : ""));
+
 	/* === Now pack all the widgets */
 	vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
 	gtk_container_add(GTK_CONTAINER(feedprop->window), vbox);
@@ -467,6 +496,30 @@ void rssyl_gtk_prop(RFolderItem *ritem)
 	gtk_container_set_border_width(GTK_CONTAINER(inner_vbox), 7);
 	gtk_container_add(GTK_CONTAINER(frame), inner_vbox);
 
+	inner_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 7);
+	/* Use default User Agent - checkbutton */
+	gtk_box_pack_start(GTK_BOX(inner_vbox), feedprop->use_default_user_agent, FALSE, FALSE, 0);
+	g_signal_connect(G_OBJECT(feedprop->use_default_user_agent), "toggled",
+			G_CALLBACK(rssyl_feedprop_togglebutton_toggled_cb),
+			(gpointer)feedprop);
+
+	/* User Agent - label */
+	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 7);
+	label = gtk_label_new(_("User Agent"));
+	gtk_widget_set_tooltip_text(feedprop->use_default_user_agent,
+			_("Disable this to use a User Agent specific to this feed"));
+	gtk_widget_set_tooltip_text(feedprop->specific_user_agent,
+			_("Specific User Agent to use for this feed. If empty, the User Agent string set in 'Preferences/Plugins/RSSyl' will be used"));
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(hbox), feedprop->specific_user_agent, FALSE, FALSE, 0);
+	gtk_widget_set_sensitive(feedprop->specific_user_agent,
+			!ritem->use_default_user_agent);
+	gtk_box_pack_start(GTK_BOX(hbox), feedprop->use_default_user_agent, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(inner_vbox), hbox, FALSE, FALSE, 0);
+	PACK_FRAME (vbox, frame, _("User Agent"));
+	gtk_container_set_border_width(GTK_CONTAINER(inner_vbox), 7);
+	gtk_container_add(GTK_CONTAINER(frame), inner_vbox);
+
 	/* Buttonbox */
 	bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
 	gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
diff --git a/src/plugins/rssyl/rssyl_feed_props.h b/src/plugins/rssyl/rssyl_feed_props.h
index eec5009f8..79852f74c 100644
--- a/src/plugins/rssyl/rssyl_feed_props.h
+++ b/src/plugins/rssyl/rssyl_feed_props.h
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2005-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2005-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -38,6 +38,8 @@ struct _RFeedProp {
 	GtkWidget *auth_type;
 	GtkWidget *auth_username;
 	GtkWidget *auth_password;
+	GtkWidget *use_default_user_agent;
+	GtkWidget *specific_user_agent;
 };
 
 typedef struct _RFeedProp RFeedProp;
diff --git a/src/plugins/rssyl/rssyl_prefs.c b/src/plugins/rssyl/rssyl_prefs.c
index cd8dec451..7c6baa903 100644
--- a/src/plugins/rssyl/rssyl_prefs.c
+++ b/src/plugins/rssyl/rssyl_prefs.c
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2005-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2005-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -35,7 +35,6 @@
 #include "rssyl_prefs.h"
 #include "rssyl_feed.h"
 
-static RPrefsPage rssyl_gtk_prefs_page;
 RPrefs rssyl_prefs;
 
 static void destroy_rssyl_prefs_page(PrefsPage *page);
@@ -55,9 +54,28 @@ static PrefParam param[] = {
 		P_STRING, NULL, NULL, NULL },
 	{ "ssl_verify_peer", "TRUE", &rssyl_prefs.ssl_verify_peer,
 		P_BOOL,	NULL, NULL, NULL },
+	{ "use_custom_user_agent", "FALSE", &rssyl_prefs.use_custom_user_agent,
+		P_BOOL, NULL, NULL, NULL },
+	{ "custom_user_agent", "", &rssyl_prefs.custom_user_agent,
+		P_STRING, NULL, NULL, NULL },
 	{ 0, 0, 0, 0, 0, 0, 0 }
 };
 
+static struct _RPrefsPage {
+	PrefsPage page;
+	GtkWidget *refresh_enabled;
+	GtkWidget *refresh;
+	GtkWidget *refresh_on_startup;
+	GtkWidget *cookies_path;
+	GtkWidget *ssl_verify_peer;
+	GtkWidget *use_custom_user_agent;
+	GtkWidget *custom_user_agent;
+};
+
+typedef struct _RPrefsPage RPrefsPage;
+
+static RPrefsPage rssyl_gtk_prefs_page;
+
 void rssyl_prefs_init(void)
 {
 	static gchar *path[3];
@@ -96,6 +114,16 @@ rssyl_refresh_enabled_toggled_cb(GtkToggleButton *tb, gpointer data)
 	return FALSE;
 }
 
+/* Toggle the custom user agent entry sensitivity after the
+ * checkbutton was toggled. */
+static gboolean
+rssyl_use_custom_user_agent_toggled_cb(GtkToggleButton *tb, gpointer data)
+{
+	gtk_widget_set_sensitive(GTK_WIDGET(data),
+			gtk_toggle_button_get_active(tb));
+	return FALSE;
+}
+
 /* Open a file select dialog and set file path to cookies entry */
 static void
 rssyl_prefs_cookies_browse_cb(GtkWidget* widget, gpointer data)
@@ -120,7 +148,7 @@ static void create_rssyl_prefs_page(PrefsPage *page,
 		GtkWindow *window, gpointer data)
 {
 	RPrefsPage *prefs_page = (RPrefsPage *) page;
-	GtkWidget *vbox, *vbox1, *vbox2;
+	GtkWidget *vbox, *vbox1, *vbox2, *vbox3;
 	GtkWidget *frame;
 	GtkWidget *refresh, *refresh_enabled, *refresh_hbox;
 	GtkWidget *label;
@@ -128,6 +156,7 @@ static void create_rssyl_prefs_page(PrefsPage *page,
 	GtkAdjustment *refresh_adj;
 	GtkWidget *cookies_path, *cookies_btn, *cookies_hbox;
 	GtkWidget *ssl_verify_peer;
+	GtkWidget *use_custom_user_agent, *custom_user_agent, *user_agent_hbox;
 
 	vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
 
@@ -185,6 +214,29 @@ static void create_rssyl_prefs_page(PrefsPage *page,
 		G_CALLBACK(rssyl_prefs_cookies_browse_cb), cookies_path);
 	gtk_box_pack_start(GTK_BOX(vbox2), cookies_hbox, FALSE, FALSE, 0);
 
+	vbox3 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
+
+	user_agent_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
+	gtk_box_pack_start(GTK_BOX(user_agent_hbox), label, FALSE, FALSE, 0);
+
+	use_custom_user_agent = gtk_check_button_new_with_label(
+			_("Use a custom User Agent"));
+	gtk_widget_set_tooltip_text(use_custom_user_agent,
+			_("Instead of using the default User Agent for feed retrieval, you can enter a custom value"));
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_custom_user_agent),
+			rssyl_prefs.use_custom_user_agent);
+	gtk_box_pack_start(GTK_BOX(user_agent_hbox), use_custom_user_agent, FALSE, FALSE, 0);
+
+	custom_user_agent = gtk_entry_new();
+	gtk_entry_set_text(GTK_ENTRY(custom_user_agent), rssyl_prefs.custom_user_agent);
+	gtk_box_pack_start(GTK_BOX(user_agent_hbox), custom_user_agent, TRUE, TRUE, 0);
+	gtk_widget_set_tooltip_text(custom_user_agent,
+			_("Custom User Agent to use for feed retrieval. If empty, the default User Agent string will be used"));
+
+	g_signal_connect(G_OBJECT(use_custom_user_agent), "toggled",
+			G_CALLBACK(rssyl_use_custom_user_agent_toggled_cb), custom_user_agent);
+	gtk_box_pack_start(GTK_BOX(vbox3), user_agent_hbox, FALSE, FALSE, 0);
+
 	vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
 	gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
 
@@ -196,6 +248,12 @@ static void create_rssyl_prefs_page(PrefsPage *page,
 	gtk_container_set_border_width(GTK_CONTAINER(vbox2), 6);
 	gtk_container_add(GTK_CONTAINER(frame), vbox2);
 
+	PACK_FRAME (vbox, frame, _("User Agent"));
+	gtk_container_set_border_width(GTK_CONTAINER(vbox3), 6);
+	gtk_container_add(GTK_CONTAINER(frame), vbox3);
+
+	SET_TOGGLE_SENSITIVITY(use_custom_user_agent, custom_user_agent);
+
 	gtk_widget_show_all(vbox);
 
 	/* Store pointers to relevant widgets */
@@ -205,6 +263,8 @@ static void create_rssyl_prefs_page(PrefsPage *page,
 	prefs_page->refresh_on_startup = refresh_on_startup;
 	prefs_page->cookies_path = cookies_path;
 	prefs_page->ssl_verify_peer = ssl_verify_peer;
+	prefs_page->use_custom_user_agent = use_custom_user_agent;
+	prefs_page->custom_user_agent = custom_user_agent;
 }
 
 static void destroy_rssyl_prefs_page(PrefsPage *page)
@@ -231,6 +291,10 @@ static void save_rssyl_prefs(PrefsPage *page)
 				GTK_ENTRY(prefs_page->cookies_path)));
 	rssyl_prefs.ssl_verify_peer = gtk_toggle_button_get_active(
 			GTK_TOGGLE_BUTTON(prefs_page->ssl_verify_peer));
+	rssyl_prefs.use_custom_user_agent = gtk_toggle_button_get_active(
+			GTK_TOGGLE_BUTTON(prefs_page->use_custom_user_agent));
+	rssyl_prefs.custom_user_agent = g_strdup(gtk_entry_get_text(
+				GTK_ENTRY(prefs_page->custom_user_agent)));
 
 	/* Store prefs in rc file */
 	pref_file = prefs_write_open(rc_file_path);
diff --git a/src/plugins/rssyl/rssyl_prefs.h b/src/plugins/rssyl/rssyl_prefs.h
index d9573a16b..eb2482400 100644
--- a/src/plugins/rssyl/rssyl_prefs.h
+++ b/src/plugins/rssyl/rssyl_prefs.h
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2005-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2005-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -31,18 +31,11 @@ struct _RPrefs {
 	gboolean refresh_on_startup;
 	gchar *cookies_path;
 	gboolean ssl_verify_peer;
+	gboolean use_custom_user_agent;
+	gchar *custom_user_agent;
 };
 
-typedef struct _RPrefsPage RPrefsPage;
-
-struct _RPrefsPage {
-	PrefsPage page;
-	GtkWidget *refresh_enabled;
-	GtkWidget *refresh;
-	GtkWidget *refresh_on_startup;
-	GtkWidget *cookies_path;
-	GtkWidget *ssl_verify_peer;
-};
+extern RPrefs rssyl_prefs;
 
 void rssyl_prefs_init(void);
 void rssyl_prefs_done(void);
diff --git a/src/plugins/rssyl/rssyl_update_comments.c b/src/plugins/rssyl/rssyl_update_comments.c
index 3cd1aa499..61782b5fb 100644
--- a/src/plugins/rssyl/rssyl_update_comments.c
+++ b/src/plugins/rssyl/rssyl_update_comments.c
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2006-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2006-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -113,6 +113,9 @@ void rssyl_update_comments(RFolderItem *ritem)
 
 					fetchctx = rssyl_prep_fetchctx_from_url(feed_item_get_comments_url(fi));
 					if (fetchctx != NULL) {
+						/* rssyl_prep_fetchctx_from_url does not initialize fetchctx->ritem,
+						   do it now for later calls to rssyl_get_user_agent() */
+						fetchctx->ritem = ritem;
 						feed_set_ssl_verify_peer(fetchctx->feed, ritem->ssl_verify_peer);
 
 						rssyl_fetch_feed(fetchctx, 0);
diff --git a/src/plugins/rssyl/rssyl_update_feed.c b/src/plugins/rssyl/rssyl_update_feed.c
index 8620959f5..1735c32dd 100644
--- a/src/plugins/rssyl/rssyl_update_feed.c
+++ b/src/plugins/rssyl/rssyl_update_feed.c
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
- * Copyright (C) 2006-2023 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
+ * Copyright (C) 2006-2025 the Claws Mail Team and Andrej Kacian <andrej at kacian.sk>
  *
  * 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
@@ -34,6 +34,7 @@
 #include <prefs_common.h>
 #include <inc.h>
 #include <main.h>
+#include <defs.h>
 
 /* Local includes */
 #include "libfeed/feed.h"
@@ -44,14 +45,59 @@
 #include "rssyl_prefs.h"
 #include "rssyl_update_comments.h"
 
-/* rssyl_fetch_feed_thr() */
+extern const gchar *plugin_version(void);
+
+/* rssyl_get_user_agent
+   returns a ptr to a newly allocated string containing either the feed's specific user agent string
+   (if set and if trimmed string is non-empty),
+   or the custom user agent string set in global preferences (if prefs tells so and if trimmed string
+   is not empty), otherwise the default user agent string.
+   caller has to free the allocated string from pointer after use.
+*/
+gchar *rssyl_get_user_agent(RFolderItem *ritem)
+{
+	gchar *user_agent = NULL; 
+
+	/* check if feed properties has a user agent enabled and set */
+	/* ritem may be NULL when call comes from an initial fetch from url (when subscribing) */
+	if (ritem != NULL && ritem->use_default_user_agent == FALSE) {
+		gchar *specific = g_strstrip(g_strdup(ritem->specific_user_agent));
+
+		if (strlen(specific) > 0)
+			user_agent = specific;
+		else
+			debug_print("RSSyl: feed-specific User Agent is empty, trying custom value from global prefs\n");
+	}
+
+	/* fallback to user agent value from preferences (if enabled and set) */
+	if (user_agent == NULL) {
+		if (rssyl_prefs.use_custom_user_agent) {
+			gchar *custom = g_strstrip(g_strdup(rssyl_prefs.custom_user_agent));
 
+			if (strlen(custom) > 0)
+				user_agent = custom;
+			else
+				debug_print("RSSyl: custom User Agent is empty, assuming default value\n");
+		}
+	}
+
+	/* fallback to default User Agent */
+	if (user_agent == NULL)
+		user_agent = g_strdup_printf("ClawsMailRSSyl/%s (%s)", (gchar *)plugin_version(), HOMEPAGE_URI);
+
+	debug_print("RSSyl: User Agent is %s\n", user_agent);
+	return user_agent;
+}
+
+/* rssyl_fetch_feed_thr() */
 static void *rssyl_fetch_feed_thr(void *arg)
 {
 	RFetchCtx *ctx = (RFetchCtx *)arg;
+	gchar *user_agent = rssyl_get_user_agent(ctx->ritem);
 
 	/* Fetch and parse the feed. */
-	ctx->response_code = feed_update(ctx->feed, -1);
+	ctx->response_code = feed_update(ctx->feed, -1, user_agent);
+	g_free(user_agent);
 
 	/* Signal main thread that we're done here. */
 	ctx->ready = TRUE;
@@ -169,6 +215,7 @@ RFetchCtx *rssyl_prep_fetchctx_from_item(RFolderItem *ritem)
 	ctx->error = NULL;
 	ctx->success = TRUE;
 	ctx->ready = FALSE;
+	ctx->ritem = ritem;
 
 	if (ritem->auth->type != FEED_AUTH_NONE)
 		ritem->auth->password = rssyl_passwd_get(ritem);
@@ -198,6 +245,7 @@ RFetchCtx *rssyl_prep_fetchctx_from_url(gchar *url)
 	ctx->error = NULL;
 	ctx->success = TRUE;
 	ctx->ready = FALSE;
+	ctx->ritem = NULL;
 
 	feed_set_timeout(ctx->feed, prefs_common_get_prefs()->io_timeout_secs);
 	feed_set_cookies_path(ctx->feed, rssyl_prefs_get()->cookies_path);
@@ -220,6 +268,7 @@ gboolean rssyl_update_feed(RFolderItem *ritem, RSSylVerboseFlags verbose)
 	MainWindow *mainwin = mainwindow_get_mainwindow();
 	gchar *msg = NULL;
 	gboolean success = FALSE;
+	gchar *user_agent = rssyl_get_user_agent(ritem);
 
 	g_return_val_if_fail(ritem != NULL, FALSE);
 	g_return_val_if_fail(ritem->url != NULL, FALSE);
@@ -227,7 +276,8 @@ gboolean rssyl_update_feed(RFolderItem *ritem, RSSylVerboseFlags verbose)
 	debug_print("RSSyl: starting to update '%s' (%s)\n",
 			ritem->item.name, ritem->url);
 
-	log_print(LOG_PROTOCOL, RSSYL_LOG_UPDATING, ritem->url);
+	log_print(LOG_PROTOCOL, RSSYL_LOG_UPDATING, ritem->url, user_agent);
+	g_free(user_agent);
 
 	msg = g_strdup_printf(_("Updating feed '%s'..."), ritem->item.name);
 	STATUSBAR_PUSH(mainwin, msg);

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list