Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package liferea for openSUSE:Factory checked in at 2023-03-14 18:17:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/liferea (Old) and /work/SRC/openSUSE:Factory/.liferea.new.31432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "liferea" Tue Mar 14 18:17:04 2023 rev:10 rq:1071305 version:1.14.1 Changes: -------- --- /work/SRC/openSUSE:Factory/liferea/liferea.changes 2023-01-20 17:39:37.996837517 +0100 +++ /work/SRC/openSUSE:Factory/.liferea.new.31432/liferea.changes 2023-03-14 18:17:13.331917022 +0100 @@ -1,0 +2,7 @@ +Mon Mar 13 09:37:27 UTC 2023 - Marcel Kuehlhorn <tu...@opensuse.org> + +- Update to version 1.14.1: + + Fix CVE-2023-1350 - Remote code execution on feed enrichment + (boo#1209190). + +------------------------------------------------------------------- Old: ---- liferea-1.14.0.tar.bz2 New: ---- liferea-1.14.1.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ liferea.spec ++++++ --- /var/tmp/diff_new_pack.Xzouq5/_old 2023-03-14 18:17:14.135921320 +0100 +++ /var/tmp/diff_new_pack.Xzouq5/_new 2023-03-14 18:17:14.143921363 +0100 @@ -17,7 +17,7 @@ Name: liferea -Version: 1.14.0 +Version: 1.14.1 Release: 0 Summary: Linux Feed Reader License: GPL-2.0-only ++++++ liferea-1.14.0.tar.bz2 -> liferea-1.14.1.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/ChangeLog new/liferea-1.14.1/ChangeLog --- old/liferea-1.14.0/ChangeLog 2023-01-10 21:08:31.000000000 +0100 +++ new/liferea-1.14.1/ChangeLog 2023-03-12 21:00:22.000000000 +0100 @@ -1,3 +1,17 @@ +2023-03-12 Lars Windolf <lars.wind...@gmx.de> + + Version 1.14.1 + + * Fixes CVE-2023-1350: RCE vulnerability on feed enrichment + (patch by Alexander Erwin Ittner) + + * Fixes #1200: Crash on double free + (mozbugbox) + + * Improve #1192 be reordering widget creation order + (Lars Windolf) + + 2023-01-10 Lars Windolf <lars.wind...@gmx.de> Version 1.14.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/configure new/liferea-1.14.1/configure --- old/liferea-1.14.0/configure 2023-01-10 21:09:02.000000000 +0100 +++ new/liferea-1.14.1/configure 2023-03-12 21:11:56.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for liferea 1.14.0. +# Generated by GNU Autoconf 2.71 for liferea 1.14.1. # # Report bugs to <liferea-de...@lists.sourceforge.net>. # @@ -621,8 +621,8 @@ # Identity of this package. PACKAGE_NAME='liferea' PACKAGE_TARNAME='liferea' -PACKAGE_VERSION='1.14.0' -PACKAGE_STRING='liferea 1.14.0' +PACKAGE_VERSION='1.14.1' +PACKAGE_STRING='liferea 1.14.1' PACKAGE_BUGREPORT='liferea-de...@lists.sourceforge.net' PACKAGE_URL='' @@ -1435,7 +1435,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures liferea 1.14.0 to adapt to many kinds of systems. +\`configure' configures liferea 1.14.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1506,7 +1506,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of liferea 1.14.0:";; + short | recursive ) echo "Configuration of liferea 1.14.1:";; esac cat <<\_ACEOF @@ -1637,7 +1637,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -liferea configure 1.14.0 +liferea configure 1.14.1 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -1855,7 +1855,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by liferea $as_me 1.14.0, which was +It was created by liferea $as_me 1.14.1, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3203,7 +3203,7 @@ # Define the identity of the package. PACKAGE='liferea' - VERSION='1.14.0' + VERSION='1.14.1' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -16861,7 +16861,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by liferea $as_me 1.14.0, which was +This file was extended by liferea $as_me 1.14.1, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16929,7 +16929,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -liferea config.status 1.14.0 +liferea config.status 1.14.1 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/configure.ac new/liferea-1.14.1/configure.ac --- old/liferea-1.14.0/configure.ac 2023-01-10 20:46:17.000000000 +0100 +++ new/liferea-1.14.1/configure.ac 2023-03-12 21:00:39.000000000 +0100 @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT([liferea],[1.14.0],[liferea-de...@lists.sourceforge.net]) +AC_INIT([liferea],[1.14.1],[liferea-de...@lists.sourceforge.net]) AC_CANONICAL_HOST AC_CONFIG_SRCDIR([src/feedlist.c]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/net.sourceforge.liferea.appdata.xml new/liferea-1.14.1/net.sourceforge.liferea.appdata.xml --- old/liferea-1.14.0/net.sourceforge.liferea.appdata.xml 2023-01-10 21:11:53.000000000 +0100 +++ new/liferea-1.14.1/net.sourceforge.liferea.appdata.xml 2023-03-09 21:33:01.000000000 +0100 @@ -200,8 +200,6 @@ Now Liferea will never allow the panes to be smaller than 5% in height or width regarding to there orientation. If a pane is smaller than 5% height/width it will be set to 30% width or 50% height on startup. - - The intention here is that panes are never invisible after startup. </li> <li> Wait for network to be fully available before updating: sometimes when real internet diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/net.sourceforge.liferea.appdata.xml.in new/liferea-1.14.1/net.sourceforge.liferea.appdata.xml.in --- old/liferea-1.14.0/net.sourceforge.liferea.appdata.xml.in 2023-01-10 21:11:50.000000000 +0100 +++ new/liferea-1.14.1/net.sourceforge.liferea.appdata.xml.in 2023-02-04 22:50:17.000000000 +0100 @@ -201,8 +201,6 @@ Now Liferea will never allow the panes to be smaller than 5% in height or width regarding to there orientation. If a pane is smaller than 5% height/width it will be set to 30% width or 50% height on startup. - - The intention here is that panes are never invisible after startup. </li> <li> Wait for network to be fully available before updating: sometimes when real internet diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/po/fr.po new/liferea-1.14.1/po/fr.po --- old/liferea-1.14.0/po/fr.po 2023-01-09 23:24:32.000000000 +0100 +++ new/liferea-1.14.1/po/fr.po 2023-02-04 22:50:17.000000000 +0100 @@ -13,15 +13,15 @@ "Project-Id-Version: Liferea 1.8\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-10-26 01:24+0200\n" -"PO-Revision-Date: 2022-09-16 10:26+0200\n" -"Last-Translator: Guillaume Bernard <associati...@guillaume-bernard.fr>\n" +"PO-Revision-Date: 2023-01-13 12:16+0100\n" +"Last-Translator: Irénée Thirion <irenee.thirion@e.email>\n" "Language-Team: français <>\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.1.1\n" +"X-Generator: Poedit 3.2.2\n" #: ../net.sourceforge.liferea.desktop.in.h:1 ../src/liferea_application.c:349 #: ../glade/mainwindow.ui.h:1 @@ -439,18 +439,17 @@ msgstr "La connexion a échoué !" #: ../src/fl_sources/google_source.c:404 -#, fuzzy msgid "Google Reader API" -msgstr "Google Reader" +msgstr "API Google Reader" #: ../src/fl_sources/google_source_feed.c:159 -#, fuzzy msgid "Could not parse JSON returned by Google Reader API!" -msgstr "Impossible dâanalyser le JSON envoyé par lâAPI Reedah !" +msgstr "" +"Impossible dâanalyser le fichier JSON retourné par lâAPI Google Reader !" #: ../src/fl_sources/node_source.c:117 msgid "Miniflux" -msgstr "" +msgstr "Miniflux" #: ../src/fl_sources/node_source.c:332 msgid "No feed list source types found!" @@ -717,30 +716,28 @@ #. http 5xx server errors #: ../src/net.c:493 -#, fuzzy msgid "Internal Server Error" -msgstr "Erreur du serveur" +msgstr "Erreur interne du serveur" #: ../src/net.c:494 msgid "Not Implemented" -msgstr "" +msgstr "Non implémenté" #: ../src/net.c:495 msgid "Bad Gateway" -msgstr "" +msgstr "Mauvaise passerelle" #: ../src/net.c:496 -#, fuzzy msgid "Service Unavailable" -msgstr "« %s » nâest pas disponible" +msgstr "Service indisponible" #: ../src/net.c:497 msgid "Gateway Timeout" -msgstr "" +msgstr "Délai dâattente de la passerelle écoulé" #: ../src/net.c:498 msgid "HTTP Version Not Supported" -msgstr "" +msgstr "Version HTTP non prise en charge" #: ../src/net.c:503 msgid "There was an internal error in the update process" @@ -819,9 +816,8 @@ msgstr "Le corps de lâélément" #: ../src/rule.c:277 -#, fuzzy msgid "Item author" -msgstr "Le corps de lâélément" +msgstr "Lâauteur de lâélément" #: ../src/rule.c:278 msgid "Read status" @@ -1091,14 +1087,14 @@ msgstr "Aucun élément nâa été sélectionné" #: ../src/ui/liferea_browser.c:482 -#, fuzzy msgid "Content download failed! Try disabling reader mode." -msgstr "Impossible de télécharger le contenu." +msgstr "" +"Impossible de télécharger le contenu. Essayez de désactiver le mode lecture." #: ../src/ui/liferea_browser.c:495 -#, fuzzy msgid "Content extraction failed! Try disabling reader mode." -msgstr "Impossible dâextraire le contenu." +msgstr "" +"Impossible dâextraire le contenu. Essayez de désactiver le mode lecture." #: ../src/ui/liferea_shell.c:409 #, c-format @@ -1325,9 +1321,8 @@ msgstr "Programme" #: ../src/ui/rule_editor.c:257 -#, fuzzy msgid "Remove" -msgstr "_Supprimer" +msgstr "Supprimer" #: ../src/ui/search_dialog.c:106 msgid "Saved Search" @@ -1504,15 +1499,16 @@ "de maintenant." #: ../glade/google_source.ui.h:1 -#, fuzzy msgid "Add Google Reader API Account" -msgstr "Ajouter un compte Google Reader" +msgstr "Ajouter un compte API Google Reader" #: ../glade/google_source.ui.h:2 msgid "" "Please enter the details of the new Google Reader API compatible " "subscription." msgstr "" +"Veuillez saisir les détails du nouvel abonnement compatible avec lâAPI " +"Google Reader." #: ../glade/google_source.ui.h:3 ../glade/reedah_source.ui.h:3 #: ../glade/theoldreader_source.ui.h:3 ../glade/ttrss_source.ui.h:4 @@ -1525,14 +1521,12 @@ msgstr "Nom dâ_utilisateur (e-mail)" #: ../glade/google_source.ui.h:5 -#, fuzzy msgid "_Server" -msgstr "URL du _serveur" +msgstr "_Serveur" #: ../glade/google_source.ui.h:6 -#, fuzzy msgid "_Name" -msgstr "_Nom du flux" +msgstr "_Nom" #: ../glade/liferea_menu.ui.h:1 msgid "_Subscriptions" @@ -1886,9 +1880,8 @@ "recherche." #: ../glade/prefs.ui.h:22 -#, fuzzy msgid "Ask for confirmation when marking all items as read." -msgstr "Demander confirmation pour marquer tous les éléments comme lus" +msgstr "Demander confirmation pour marquer tous les éléments comme lus." #: ../glade/prefs.ui.h:23 msgid "Web Integration" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/po/liferea.pot new/liferea-1.14.1/po/liferea.pot --- old/liferea-1.14.0/po/liferea.pot 2023-01-10 21:11:53.000000000 +0100 +++ new/liferea-1.14.1/po/liferea.pot 2023-03-12 21:12:00.000000000 +0100 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-10 21:11+0100\n" +"POT-Creation-Date: 2023-03-12 21:12+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <l...@li.org>\n" @@ -706,16 +706,16 @@ msgid "Create News Bin" msgstr "" -#: ../src/node.c:624 +#: ../src/node.c:625 #, c-format msgid "Failed to create feed file: %s" msgstr "" -#: ../src/node.c:643 +#: ../src/node.c:644 msgid "Feed file exported from Liferea" msgstr "" -#: ../src/node.c:658 +#: ../src/node.c:659 #, c-format msgid "Error while saving feed file" msgstr "" @@ -846,12 +846,12 @@ msgid "\"%s\" has not changed since last update" msgstr "" -#: ../src/subscription.c:221 ../src/subscription.c:296 +#: ../src/subscription.c:221 ../src/subscription.c:297 #, c-format msgid "Updating (%d / %d) ..." msgstr "" -#: ../src/subscription.c:298 +#: ../src/subscription.c:299 #, c-format msgid "Updating '%s'..." msgstr "" @@ -1277,28 +1277,28 @@ msgid "All Files" msgstr "" -#: ../src/update.c:370 +#: ../src/update.c:377 #, c-format msgid "Error opening temp file %s to use for filtering!" msgstr "" -#: ../src/update.c:392 +#: ../src/update.c:399 #, c-format msgid "%s exited with status %d" msgstr "" -#: ../src/update.c:398 ../src/update.c:399 ../src/update.c:621 +#: ../src/update.c:405 ../src/update.c:406 ../src/update.c:628 #, c-format msgid "Error: Could not open pipe \"%s\"" msgstr "" #. FIXME: maybe setting request->returncode would be better -#: ../src/update.c:652 +#: ../src/update.c:659 #, c-format msgid "Error: Could not open file \"%s\"" msgstr "" -#: ../src/update.c:658 +#: ../src/update.c:665 #, c-format msgid "Error: There is no file \"%s\"" msgstr "" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/common.c new/liferea-1.14.1/src/common.c --- old/liferea-1.14.0/src/common.c 2022-03-30 23:40:17.000000000 +0200 +++ new/liferea-1.14.1/src/common.c 2023-03-09 23:13:43.000000000 +0100 @@ -138,7 +138,9 @@ g_assert (NULL != url); /* xmlURIEscape returns NULL if spaces are in the URL, - so we need to replace them first (see SF #2965158) */ + so we need to replace them first (see SF #2965158). + TODO: perhaps replace xmlURIEscape with g_uri_escape_string ? + */ tmp = (xmlChar *)common_strreplace (g_strdup ((gchar *)url), " ", "%20"); result = xmlURIEscape (tmp); g_free (tmp); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/feed.c new/liferea-1.14.1/src/feed.c --- old/liferea-1.14.0/src/feed.c 2022-07-23 17:27:38.000000000 +0200 +++ new/liferea-1.14.1/src/feed.c 2023-03-09 23:13:43.000000000 +0100 @@ -460,7 +460,7 @@ NODE_CAPABILITY_EXPORT | NODE_CAPABILITY_EXPORT_ITEMS, "feed", /* not used, feed format ids are used instead */ - NULL, + ICON_DEFAULT, feed_import, feed_export, feed_load, @@ -472,7 +472,6 @@ feed_properties, feed_free }; - nti.icon = icon_get (ICON_DEFAULT); return &nti; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/feed_parser.h new/liferea-1.14.1/src/feed_parser.h --- old/liferea-1.14.0/src/feed_parser.h 2021-12-17 22:10:50.000000000 +0100 +++ new/liferea-1.14.1/src/feed_parser.h 2023-02-04 22:50:17.000000000 +0100 @@ -1,7 +1,7 @@ /** * @file feed_parser.h parsing of different feed formats * - * Copyright (C) 2008-2021 Lars Windolf <lars.wind...@gmx.de> + * Copyright (C) 2008-2023 Lars Windolf <lars.wind...@gmx.de> * * 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 @@ -30,7 +30,7 @@ subscriptionPtr subscription; /**< the subscription the feed belongs to (optional) */ feedPtr feed; /**< the feed structure to fill */ GList *items; /**< the list of new items */ - struct item *item; /**< the item currently parsed (or NULL) */ + itemPtr item; /**< the item currently parsed (or NULL) */ GHashTable *tmpdata; /**< tmp data hash used during stateful parsing */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/fl_sources/node_source.c new/liferea-1.14.1/src/fl_sources/node_source.c --- old/liferea-1.14.0/src/fl_sources/node_source.c 2022-07-23 17:27:38.000000000 +0200 +++ new/liferea-1.14.1/src/fl_sources/node_source.c 2023-03-09 23:13:43.000000000 +0100 @@ -1,7 +1,7 @@ /* * @file node_source.c generic node source provider implementation * - * Copyright (C) 2005-2022 Lars Windolf <lars.wind...@gmx.de> + * Copyright (C) 2005-2023 Lars Windolf <lars.wind...@gmx.de> * * 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 @@ -622,7 +622,7 @@ /* derive the node source node type from the folder node type */ nodeType = (nodeTypePtr) g_new0 (struct nodeType, 1); nodeType->id = "source"; - nodeType->icon = icon_get (ICON_DEFAULT); + nodeType->icon = ICON_DEFAULT; nodeType->capabilities = NODE_CAPABILITY_SHOW_UNREAD_COUNT | NODE_CAPABILITY_SHOW_ITEM_FAVICONS | NODE_CAPABILITY_UPDATE_CHILDS | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/folder.c new/liferea-1.14.1/src/folder.c --- old/liferea-1.14.0/src/folder.c 2023-01-09 23:24:32.000000000 +0100 +++ new/liferea-1.14.1/src/folder.c 2023-03-09 23:13:43.000000000 +0100 @@ -119,7 +119,7 @@ NODE_CAPABILITY_UPDATE_CHILDS | NODE_CAPABILITY_EXPORT, "folder", - NULL, + ICON_FOLDER, folder_import, folder_export, folder_load, @@ -131,7 +131,6 @@ feed_list_view_rename_node, NULL }; - fnti.icon = icon_get (ICON_FOLDER); return &fnti; } @@ -150,7 +149,7 @@ NODE_CAPABILITY_UPDATE_CHILDS | NODE_CAPABILITY_EXPORT, "root", - NULL, /* and no need for an icon */ + 0, /* and no need for an icon */ folder_import, folder_export, folder_load, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/html.c new/liferea-1.14.1/src/html.c --- old/liferea-1.14.0/src/html.c 2022-03-31 23:02:07.000000000 +0200 +++ new/liferea-1.14.1/src/html.c 2023-03-09 23:13:43.000000000 +0100 @@ -221,7 +221,7 @@ GSList * html_auto_discover_feed (const gchar* data, const gchar *defaultBaseUri) { - GSList *iter, *links = NULL; + GSList *iter, *links = NULL, *valid_links = NULL; gchar *baseUri = NULL; xmlDocPtr doc; xmlNodePtr node, root; @@ -253,17 +253,25 @@ /* Turn relative URIs into absolute URIs */ iter = links; while (iter) { - gchar *tmp = iter->data; - iter->data = common_build_url (tmp, baseUri); - g_free (tmp); - debug1 (DEBUG_UPDATE, "search result: %s", (gchar *)iter->data); + gchar *tmp = (gchar *)common_build_url (iter->data, baseUri); + + /* We expect only relative URIs starting with '/' or absolute URIs starting with 'http://' or 'https://' */ + if ('h' == tmp[0] || '/' == tmp[0]) { + debug1 (DEBUG_UPDATE, "search result: %s", (gchar *)iter->data); + valid_links = g_slist_append (valid_links, tmp); + } else { + debug1 (DEBUG_UPDATE, "html_auto_discover_feed: discarding invalid URL %s", tmp ? tmp : "NULL"); + g_free (tmp); + } + iter = g_slist_next (iter); } + g_slist_free_full (links, g_free); g_free (baseUri); xmlFreeDoc (doc); - return links; + return valid_links; } GSList * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/item.c new/liferea-1.14.1/src/item.c --- old/liferea-1.14.0/src/item.c 2022-10-12 01:13:23.000000000 +0200 +++ new/liferea-1.14.1/src/item.c 2023-03-09 23:13:43.000000000 +0100 @@ -1,7 +1,7 @@ /** * @file item.c item handling * - * Copyright (C) 2003-2021 Lars Windolf <lars.wind...@gmx.de> + * Copyright (C) 2003-2023 Lars Windolf <lars.wind...@gmx.de> * Copyright (C) 2004-2006 Nathan J. Conrad <t98...@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify @@ -34,27 +34,55 @@ #include "render.h" #include "xml.h" -itemPtr -item_new (void) +G_DEFINE_TYPE (LifereaItem, liferea_item, G_TYPE_OBJECT); + +static void +liferea_item_finalize (GObject *object) { - itemPtr item; + LifereaItem *item = LIFEREA_ITEM (object); + + g_free (item->title); + g_free (item->source); + g_free (item->sourceId); + g_free (item->description); + g_free (item->commentFeedId); + g_free (item->nodeId); + g_free (item->parentNodeId); - item = g_new0 (struct item, 1); + g_assert (NULL == item->tmpdata); /* should be free after rendering */ + metadata_list_free (item->metadata); +} + +static void +liferea_item_class_init (LifereaItemClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = liferea_item_finalize; +} + +static void +liferea_item_init (LifereaItem *item) +{ item->popupStatus = TRUE; +} - return item; +LifereaItem * +item_new (void) +{ + return LIFEREA_ITEM (g_object_new (LIFEREA_ITEM_TYPE, NULL)); } -itemPtr +LifereaItem * item_load (gulong id) { return db_item_load (id); } -itemPtr -item_copy (itemPtr item) +LifereaItem * +item_copy (LifereaItem *item) { - itemPtr copy = item_new (); + LifereaItem *copy = item_new (); item_set_title (copy, item->title); item_set_source (copy, item->source); @@ -84,7 +112,7 @@ } void -item_set_title (itemPtr item, const gchar * title) +item_set_title (LifereaItem *item, const gchar * title) { g_free (item->title); @@ -95,7 +123,7 @@ } void -item_set_description (itemPtr item, const gchar *description) +item_set_description (LifereaItem *item, const gchar *description) { if (!description) return; @@ -109,39 +137,41 @@ } void -item_set_source (itemPtr item, const gchar * source) +item_set_source (LifereaItem *item, const gchar * source) { g_free (item->source); - if (source) + + /* We expect only relative URIs starting with '/' or absolute URIs starting with 'http://' or 'https://' */ + if (source && ('/' == source[0] || 'h' == source[0])) item->source = g_strstrip (g_strdup (source)); else item->source = NULL; } void -item_set_id (itemPtr item, const gchar * id) +item_set_id (LifereaItem *item, const gchar * id) { g_free (item->sourceId); item->sourceId = g_strdup (id); } void -item_set_time (itemPtr item, gint64 time) +item_set_time (LifereaItem *item, gint64 time) { item->time = time; if (item->time > 0) item->validTime = TRUE; } -const gchar * item_get_id(itemPtr item) { return item->sourceId; } -const gchar * item_get_title(itemPtr item) {return item->title; } -const gchar * item_get_description(itemPtr item) { return item->description; } -const gchar * item_get_source(itemPtr item) { return item->source; } +const gchar * item_get_id(LifereaItem *item) { return item->sourceId; } +const gchar * item_get_title(LifereaItem *item) {return item->title; } +const gchar * item_get_description(LifereaItem *item) { return item->description; } +const gchar * item_get_source(LifereaItem *item) { return item->source; } static GRegex *whitespace_strip_re = NULL; gchar * -item_get_teaser (itemPtr item) +item_get_teaser (LifereaItem *item) { gchar *input, *tmpDesc; gchar *teaser = NULL; @@ -176,7 +206,7 @@ } gchar * -item_make_link (itemPtr item) +item_make_link (LifereaItem *item) { const gchar *src; gchar *link; @@ -202,7 +232,7 @@ } const gchar * -item_get_author(itemPtr item) +item_get_author(LifereaItem *item) { gchar *author; @@ -210,25 +240,8 @@ return author; } -void -item_unload (itemPtr item) -{ - g_free (item->title); - g_free (item->source); - g_free (item->sourceId); - g_free (item->description); - g_free (item->commentFeedId); - g_free (item->nodeId); - g_free (item->parentNodeId); - - g_assert (NULL == item->tmpdata); /* should be free after rendering */ - metadata_list_free (item->metadata); - - g_free (item); -} - const gchar * -item_get_base_url (itemPtr item) +item_get_base_url (LifereaItem *item) { /* item->node is always the source node for the item never a search folder or folder */ @@ -236,7 +249,7 @@ } void -item_to_xml (itemPtr item, gpointer xmlNode) +item_to_xml (LifereaItem *item, gpointer xmlNode) { xmlNodePtr parentNode = (xmlNodePtr)xmlNode; xmlNodePtr duplicatesNode; @@ -293,7 +306,7 @@ duplicates = iter = db_item_get_duplicates(item->sourceId); while (iter) { gulong id = GPOINTER_TO_UINT (iter->data); - itemPtr duplicate = item_load (id); + LifereaItem * duplicate = item_load (id); if (duplicate) { nodePtr duplicateNode = node_from_id (duplicate->nodeId); if (duplicateNode && (item->id != duplicate->id)) @@ -328,7 +341,7 @@ } static const gchar * -item_get_text_direction (itemPtr item) +item_get_text_direction (LifereaItem *item) { if (item_get_title (item)) return (common_get_text_direction (item_get_title (item))); @@ -340,7 +353,7 @@ } gchar * -item_render (itemPtr item, guint viewMode) +item_render (LifereaItem *item, guint viewMode) { renderParamPtr params; gchar *output = NULL, *baseUrl = NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/item.h new/liferea-1.14.1/src/item.h --- old/liferea-1.14.0/src/item.h 2022-10-12 01:13:35.000000000 +0200 +++ new/liferea-1.14.1/src/item.h 2023-02-04 22:50:17.000000000 +0100 @@ -1,7 +1,7 @@ /* * @file item.h item handling * - * Copyright (C) 2003-2022 Lars Windolf <lars.wind...@gmx.de> + * Copyright (C) 2003-2023 Lars Windolf <lars.wind...@gmx.de> * Copyright (C) 2004-2006 Nathan J. Conrad <t98...@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify @@ -23,24 +23,27 @@ #define _ITEM_H #include <glib.h> +#include <glib-object.h> -/* Currently Liferea knows only a single type of items used - for the itemset types feed, folder and search folder. So each - feed list type provider must provide it's data using the - item interface. */ - -/* ------------------------------------------------------------ */ -/* item interface */ -/* ------------------------------------------------------------ */ +/* Each feed/subscription type provider must provide it's data using `Item` */ + +G_BEGIN_DECLS + +#define LIFEREA_ITEM_TYPE (liferea_item_get_type ()) +G_DECLARE_FINAL_TYPE (LifereaItem, liferea_item, LIFEREA, ITEM, GObject) /* * An item stores a particular entry in a feed or a search. + * * Each item belongs to an item set. An itemset is a collection * of items. There are different item set types (e.g. feed, - * folder,vfolder or plugin). Each item has a source node. + * folder, search folder or plugin). Each item has a source node. * The item set node and the item source node is different - * for folders and vfolders. */ -typedef struct item { + * for folders and search folders. + */ +struct _LifereaItem { + GObject parent_instance; + gulong id; /*<< internally unique item id */ /* those fields should not be accessed directly. Accessors are provided. */ @@ -75,7 +78,9 @@ /* remote states used during sync of remote accounts */ gboolean remoteReadStatus; /*<< TRUE if the remote copy of the item has been read */ gboolean remoteFlagStatus; /*<< TRUE if the remote copy of the item has been flagged */ -} *itemPtr; +}; + +typedef struct _LifereaItem *itemPtr; /** * item_new: (skip) @@ -83,7 +88,7 @@ * * Returns: (transfer full): the new structure */ -itemPtr item_new(void); +LifereaItem * item_new(void); /** * item_load: (skip) @@ -95,7 +100,10 @@ * * Returns: (transfer full) (nullable): item structure */ -itemPtr item_load(gulong id); +LifereaItem * item_load(gulong id); + +// For legacy code let's keep item_unload() +#define item_unload(a) g_object_unref(a) /** * item_copy: (skip) @@ -107,7 +115,7 @@ * * Returns: (transfer full): copy of the item. */ -itemPtr item_copy(itemPtr item); +LifereaItem * item_copy(LifereaItem * item); /** * item_get_base_url: (skip) @@ -117,27 +125,17 @@ * * Returns: base URL */ -const gchar * item_get_base_url(itemPtr item); - -/** - * item_unload: (skip) - * @item: the item to unload - * - * Free the memory used by an itempointer. The item needs to be - * removed from the itemlist before calling this function. - * - */ -void item_unload(itemPtr item); +const gchar * item_get_base_url(LifereaItem *item); /* methods to access properties */ /* Returns the id of item. */ -const gchar * item_get_id(itemPtr item); +const gchar * item_get_id(LifereaItem *item); /* Returns the title of item. */ -const gchar * item_get_title(itemPtr item); +const gchar * item_get_title(LifereaItem *item); /* Returns the description of item. */ -const gchar * item_get_description(itemPtr item); +const gchar * item_get_description(LifereaItem *item); /* Returns the source of item. */ -const gchar * item_get_source(itemPtr item); +const gchar * item_get_source(LifereaItem *item); /** * item_get_teaser: (skip) @@ -147,7 +145,7 @@ * * Returns: (transfer full): newly allocated string to be free'd using g_free() (or NULL) */ -gchar * item_get_teaser(itemPtr item); +gchar * item_get_teaser(LifereaItem *item); /** * item_make_link: (skip) @@ -157,7 +155,7 @@ * * Returns: (transfer full): newly allocated URI to be free'd using g_free() */ -gchar * item_make_link(itemPtr item); +gchar * item_make_link(LifereaItem *item); /** * item_get_author: (skip) @@ -167,7 +165,7 @@ * * Returns: pointer to string in GSList meta data */ -const gchar * item_get_author (itemPtr item); +const gchar * item_get_author(LifereaItem *item); /** * item_set_title: (skip) @@ -176,7 +174,7 @@ * * Sets the item title */ -void item_set_title(itemPtr item, const gchar * title); +void item_set_title(LifereaItem *item, const gchar * title); /** * item_set_description: (skip) @@ -187,7 +185,7 @@ * will merge the new description against the old one deciding * on the best to keep. */ -void item_set_description (itemPtr item, const gchar *description); +void item_set_description (LifereaItem *item, const gchar *description); /** * item_set_source: (skip) @@ -196,7 +194,7 @@ * * Sets the item source */ -void item_set_source(itemPtr item, const gchar * source); +void item_set_source(LifereaItem *item, const gchar * source); /** * item_set_id: (skip) @@ -205,7 +203,7 @@ * * Sets the item id */ -void item_set_id (itemPtr item, const gchar * id); +void item_set_id (LifereaItem *item, const gchar * id); /** * item_set_time: (skip) @@ -215,7 +213,7 @@ * Sets the item time. Always use this when a valid date was * supplied for the item! */ -void item_set_time (itemPtr item, gint64 time); +void item_set_time (LifereaItem *item, gint64 time); /** * item_to_xml: (skip) @@ -225,7 +223,7 @@ * Adds an XML node to the given item. * */ -void item_to_xml (itemPtr item, gpointer parentNode); +void item_to_xml (LifereaItem *item, gpointer parentNode); /** * item_render: (skip) @@ -236,6 +234,8 @@ * * Returns XML string (to be free'd using g_free()) */ -gchar * item_render (itemPtr item, guint viewMode); +gchar * item_render (LifereaItem *item, guint viewMode); + +G_END_DECLS -#endif +#endif \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/itemlist.c new/liferea-1.14.1/src/itemlist.c --- old/liferea-1.14.0/src/itemlist.c 2023-01-09 23:24:32.000000000 +0100 +++ new/liferea-1.14.1/src/itemlist.c 2023-02-04 22:50:17.000000000 +0100 @@ -237,9 +237,9 @@ if (itemlist->priv->deferredRemove) { itemlist->priv->deferredRemove = FALSE; itemlist_remove_item (item); + } else { + item_unload (item); } - - item_unload (item); } static void @@ -499,16 +499,8 @@ while (iter) { itemPtr item = (itemPtr) iter->data; - - if (itemlist->priv->selectedId != item->id) { - /* don't call itemlist_remove_item() here, because it's to slow */ - itemview_remove_item (item); - db_item_remove (item->id); - } else { - /* go the normal and selection-safe way to avoid disturbing the user */ - itemlist_request_remove_item (item); - } - item_unload (item); + itemlist_request_remove_item (item); + db_item_remove (item->id); iter = g_list_next (iter); } @@ -590,7 +582,7 @@ } if (item) - item_unload (item); + g_object_unref (item); debug_end_measurement (DEBUG_GUI, "itemlist selection"); debug_exit ("itemlist_selection_changed"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/itemset.c new/liferea-1.14.1/src/itemset.c --- old/liferea-1.14.0/src/itemset.c 2022-10-12 01:13:43.000000000 +0200 +++ new/liferea-1.14.1/src/itemset.c 2023-02-04 22:50:17.000000000 +0100 @@ -44,7 +44,7 @@ itemPtr item = item_load (GPOINTER_TO_UINT (iter->data)); if (item) { (*callback) (item, userdata); - item_unload (item); + g_object_unref (item); } iter = g_list_next (iter); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/newsbin.c new/liferea-1.14.1/src/newsbin.c --- old/liferea-1.14.0/src/newsbin.c 2022-03-30 23:40:17.000000000 +0200 +++ new/liferea-1.14.1/src/newsbin.c 2023-03-09 23:13:43.000000000 +0100 @@ -217,7 +217,7 @@ NODE_CAPABILITY_SHOW_ITEM_COUNT | NODE_CAPABILITY_EXPORT_ITEMS; nodeType->id = "newsbin"; - nodeType->icon = icon_get (ICON_NEWSBIN); + nodeType->icon = ICON_NEWSBIN; nodeType->load = feed_get_node_type()->load; nodeType->import = newsbin_import; nodeType->export = newsbin_export; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/node.c new/liferea-1.14.1/src/node.c --- old/liferea-1.14.0/src/node.c 2023-01-09 23:24:32.000000000 +0100 +++ new/liferea-1.14.1/src/node.c 2023-03-09 23:13:43.000000000 +0100 @@ -43,6 +43,7 @@ #include "date.h" #include "fl_sources/node_source.h" #include "ui/feed_list_view.h" +#include "ui/icons.h" #include "ui/liferea_shell.h" static GHashTable *nodes = NULL; /*<< node id -> node lookup table */ @@ -431,7 +432,7 @@ node_get_icon (nodePtr node) { if (!node->icon) - return (gpointer) NODE_TYPE(node)->icon; + return (gpointer) icon_get (NODE_TYPE(node)->icon); return node->icon; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/node_type.h new/liferea-1.14.1/src/node_type.h --- old/liferea-1.14.0/src/node_type.h 2022-03-30 23:40:17.000000000 +0200 +++ new/liferea-1.14.1/src/node_type.h 2023-03-09 23:13:43.000000000 +0100 @@ -54,7 +54,7 @@ typedef struct nodeType { gulong capabilities; /**< bitmask of node type capabilities */ const gchar *id; /**< type id (used for type attribute in OPML export) */ - const GIcon *icon; /**< default icon for nodes of this type (if no favicon available) */ + guint icon; /**< default icon for nodes of this type (if no favicon available) */ /* For method documentation see the wrappers defined below! All methods are mandatory for each node type. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/subscription.c new/liferea-1.14.1/src/subscription.c --- old/liferea-1.14.0/src/subscription.c 2023-01-09 23:24:32.000000000 +0100 +++ new/liferea-1.14.1/src/subscription.c 2023-03-09 23:12:30.000000000 +0100 @@ -282,6 +282,7 @@ subscription->updateState, subscription->updateOptions ); + update_request_allow_commands (request, TRUE); if (subscription_get_filter (subscription)) request->filtercmd = g_strdup (subscription_get_filter (subscription)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/tests/Makefile.am new/liferea-1.14.1/src/tests/Makefile.am --- old/liferea-1.14.0/src/tests/Makefile.am 2022-10-13 17:37:46.000000000 +0200 +++ new/liferea-1.14.1/src/tests/Makefile.am 2023-03-09 23:13:43.000000000 +0100 @@ -2,7 +2,7 @@ noinst_PROGRAMS = $(TEST_PROGS) -TEST_PROGS = parse_html favicon parse_date parse_xml social +TEST_PROGS = parse_html favicon parse_date parse_rss parse_xml social test: $(TEST_PROGS) echo $(TEST_PROGS) |\ @@ -93,6 +93,9 @@ parse_date_CFLAGS = $(AM_CPPFLAGS) parse_date_LDADD = $(favicon_LDADD) +parse_rss_CFLAGS = $(AM_CPPFLAGS) +parse_rss_LDADD = $(favicon_LDADD) + parse_xml_CFLAGS = $(AM_CPPFLAGS) parse_xml_LDADD = $(favicon_LDADD) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/tests/Makefile.in new/liferea-1.14.1/src/tests/Makefile.in --- old/liferea-1.14.0/src/tests/Makefile.in 2023-01-10 21:09:21.000000000 +0100 +++ new/liferea-1.14.1/src/tests/Makefile.in 2023-03-12 21:11:56.000000000 +0100 @@ -100,7 +100,8 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__EXEEXT_1 = parse_html$(EXEEXT) favicon$(EXEEXT) \ - parse_date$(EXEEXT) parse_xml$(EXEEXT) social$(EXEEXT) + parse_date$(EXEEXT) parse_rss$(EXEEXT) parse_xml$(EXEEXT) \ + social$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) favicon_SOURCES = favicon.c favicon_OBJECTS = favicon-favicon.$(OBJEXT) @@ -154,6 +155,12 @@ parse_html_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(parse_html_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +parse_rss_SOURCES = parse_rss.c +parse_rss_OBJECTS = parse_rss-parse_rss.$(OBJEXT) +parse_rss_DEPENDENCIES = $(am__DEPENDENCIES_2) +parse_rss_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(parse_rss_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ parse_xml_SOURCES = parse_xml.c parse_xml_OBJECTS = parse_xml-parse_xml.$(OBJEXT) parse_xml_DEPENDENCIES = $(am__DEPENDENCIES_2) @@ -184,6 +191,7 @@ am__depfiles_remade = ./$(DEPDIR)/favicon-favicon.Po \ ./$(DEPDIR)/parse_date-parse_date.Po \ ./$(DEPDIR)/parse_html-parse_html.Po \ + ./$(DEPDIR)/parse_rss-parse_rss.Po \ ./$(DEPDIR)/parse_xml-parse_xml.Po \ ./$(DEPDIR)/social-social.Po am__mv = mv -f @@ -205,9 +213,10 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = favicon.c parse_date.c parse_html.c parse_xml.c social.c -DIST_SOURCES = favicon.c parse_date.c parse_html.c parse_xml.c \ +SOURCES = favicon.c parse_date.c parse_html.c parse_rss.c parse_xml.c \ social.c +DIST_SOURCES = favicon.c parse_date.c parse_html.c parse_rss.c \ + parse_xml.c social.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -401,7 +410,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -TEST_PROGS = parse_html favicon parse_date parse_xml social +TEST_PROGS = parse_html favicon parse_date parse_rss parse_xml social AM_CPPFLAGS = \ -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ -DPACKAGE_LIB_DIR=\""$(pkglibdir)"\" \ @@ -472,6 +481,8 @@ parse_html_LDADD = $(favicon_LDADD) parse_date_CFLAGS = $(AM_CPPFLAGS) parse_date_LDADD = $(favicon_LDADD) +parse_rss_CFLAGS = $(AM_CPPFLAGS) +parse_rss_LDADD = $(favicon_LDADD) parse_xml_CFLAGS = $(AM_CPPFLAGS) parse_xml_LDADD = $(favicon_LDADD) social_CFLAGS = $(AM_CPPFLAGS) @@ -531,6 +542,10 @@ @rm -f parse_html$(EXEEXT) $(AM_V_CCLD)$(parse_html_LINK) $(parse_html_OBJECTS) $(parse_html_LDADD) $(LIBS) +parse_rss$(EXEEXT): $(parse_rss_OBJECTS) $(parse_rss_DEPENDENCIES) $(EXTRA_parse_rss_DEPENDENCIES) + @rm -f parse_rss$(EXEEXT) + $(AM_V_CCLD)$(parse_rss_LINK) $(parse_rss_OBJECTS) $(parse_rss_LDADD) $(LIBS) + parse_xml$(EXEEXT): $(parse_xml_OBJECTS) $(parse_xml_DEPENDENCIES) $(EXTRA_parse_xml_DEPENDENCIES) @rm -f parse_xml$(EXEEXT) $(AM_V_CCLD)$(parse_xml_LINK) $(parse_xml_OBJECTS) $(parse_xml_LDADD) $(LIBS) @@ -548,6 +563,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/favicon-favicon.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_date-parse_date.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_html-parse_html.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_rss-parse_rss.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_xml-parse_xml.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/social-social.Po@am__quote@ # am--include-marker @@ -620,6 +636,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parse_html_CFLAGS) $(CFLAGS) -c -o parse_html-parse_html.obj `if test -f 'parse_html.c'; then $(CYGPATH_W) 'parse_html.c'; else $(CYGPATH_W) '$(srcdir)/parse_html.c'; fi` +parse_rss-parse_rss.o: parse_rss.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parse_rss_CFLAGS) $(CFLAGS) -MT parse_rss-parse_rss.o -MD -MP -MF $(DEPDIR)/parse_rss-parse_rss.Tpo -c -o parse_rss-parse_rss.o `test -f 'parse_rss.c' || echo '$(srcdir)/'`parse_rss.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parse_rss-parse_rss.Tpo $(DEPDIR)/parse_rss-parse_rss.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parse_rss.c' object='parse_rss-parse_rss.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parse_rss_CFLAGS) $(CFLAGS) -c -o parse_rss-parse_rss.o `test -f 'parse_rss.c' || echo '$(srcdir)/'`parse_rss.c + +parse_rss-parse_rss.obj: parse_rss.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parse_rss_CFLAGS) $(CFLAGS) -MT parse_rss-parse_rss.obj -MD -MP -MF $(DEPDIR)/parse_rss-parse_rss.Tpo -c -o parse_rss-parse_rss.obj `if test -f 'parse_rss.c'; then $(CYGPATH_W) 'parse_rss.c'; else $(CYGPATH_W) '$(srcdir)/parse_rss.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parse_rss-parse_rss.Tpo $(DEPDIR)/parse_rss-parse_rss.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parse_rss.c' object='parse_rss-parse_rss.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parse_rss_CFLAGS) $(CFLAGS) -c -o parse_rss-parse_rss.obj `if test -f 'parse_rss.c'; then $(CYGPATH_W) 'parse_rss.c'; else $(CYGPATH_W) '$(srcdir)/parse_rss.c'; fi` + parse_xml-parse_xml.o: parse_xml.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parse_xml_CFLAGS) $(CFLAGS) -MT parse_xml-parse_xml.o -MD -MP -MF $(DEPDIR)/parse_xml-parse_xml.Tpo -c -o parse_xml-parse_xml.o `test -f 'parse_xml.c' || echo '$(srcdir)/'`parse_xml.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parse_xml-parse_xml.Tpo $(DEPDIR)/parse_xml-parse_xml.Po @@ -781,6 +811,7 @@ -rm -f ./$(DEPDIR)/favicon-favicon.Po -rm -f ./$(DEPDIR)/parse_date-parse_date.Po -rm -f ./$(DEPDIR)/parse_html-parse_html.Po + -rm -f ./$(DEPDIR)/parse_rss-parse_rss.Po -rm -f ./$(DEPDIR)/parse_xml-parse_xml.Po -rm -f ./$(DEPDIR)/social-social.Po -rm -f Makefile @@ -831,6 +862,7 @@ -rm -f ./$(DEPDIR)/favicon-favicon.Po -rm -f ./$(DEPDIR)/parse_date-parse_date.Po -rm -f ./$(DEPDIR)/parse_html-parse_html.Po + -rm -f ./$(DEPDIR)/parse_rss-parse_rss.Po -rm -f ./$(DEPDIR)/parse_xml-parse_xml.Po -rm -f ./$(DEPDIR)/social-social.Po -rm -f Makefile diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/tests/parse_html.c new/liferea-1.14.1/src/tests/parse_html.c --- old/liferea-1.14.0/src/tests/parse_html.c 2022-10-10 22:52:34.000000000 +0200 +++ new/liferea-1.14.1/src/tests/parse_html.c 2023-03-09 23:13:43.000000000 +0100 @@ -1,7 +1,7 @@ /** - * @file html.c Test cases for feed link auto discovery + * @file parse_html.c Test cases for feed link auto discovery * - * Copyright (C) 2014-2019 Lars Windolf <lars.wind...@gmx.de> + * Copyright (C) 2014-2023 Lars Windolf <lars.wind...@gmx.de> * * 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 @@ -20,6 +20,7 @@ #include <glib.h> +#include "debug.h" #include "html.h" /* We need two groups of autodiscovery test cases, one for the tag soup fuzzy @@ -115,6 +116,13 @@ NULL }; +// Injection via "|"" command must not result in command subscription +gchar *tc_xml_rce[] = { + "<html><head><link rel=\"alternate\" type=\"application/rss+xml\" href=\"|date >/tmp/bad-feed-discovery.txt\"></html>", + NULL, + NULL +}; + /* HTML5 extraction test cases */ gchar *tc_article[] = { @@ -214,6 +222,9 @@ { g_test_init (&argc, &argv, NULL); + if (argv[1] && g_str_equal (argv[1], "--debug")) + set_debug_level (DEBUG_UPDATE | DEBUG_HTML | DEBUG_PARSING); + g_test_add_data_func ("/html/auto_discover_link_xml", &tc_xml, &tc_auto_discover_link); g_test_add_data_func ("/html/auto_discover_link_xml_base_url", &tc_xml_base_url, &tc_auto_discover_link); g_test_add_data_func ("/html/auto_discover_link_rss", &tc_rss, &tc_auto_discover_link); @@ -225,6 +236,7 @@ g_test_add_data_func ("/html/auto_discover_link_xml_atom", &tc_xml_atom, &tc_auto_discover_link); g_test_add_data_func ("/html/auto_discover_link_xml_atom2", &tc_xml_atom2, &tc_auto_discover_link); g_test_add_data_func ("/html/auto_discover_link_xml_atom3", &tc_xml_atom3, &tc_auto_discover_link); + g_test_add_data_func ("/html/auto_discover_link_xml_rce", &tc_xml_rce, &tc_auto_discover_link); g_test_add_data_func ("/html/html5_extract_article", &tc_article, &tc_get_article); g_test_add_data_func ("/html/html5_extract_article_main", &tc_article_main, &tc_get_article); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/tests/parse_rss.c new/liferea-1.14.1/src/tests/parse_rss.c --- old/liferea-1.14.0/src/tests/parse_rss.c 1970-01-01 01:00:00.000000000 +0100 +++ new/liferea-1.14.1/src/tests/parse_rss.c 2023-03-09 23:13:43.000000000 +0100 @@ -0,0 +1,128 @@ +/** + * @file parse_rss.c Test cases for RSS parsing + * + * Copyright (C) 2023 Lars Windolf <lars.wind...@gmx.de> + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <glib.h> +#include <string.h> + +#include "debug.h" +#include "feed.h" +#include "feed_parser.h" +#include "item.h" +#include "subscription.h" +#include "xml.h" + +/* Format of test cases: + + 1. feed XML string + 2. "true" for successfully parsed feed, "false" for unparseable + 3. number of items + 4..n string of XML serialized items + */ + +gchar *tc_rss_feed1[] = { + "<rss version=\"2.0\"><channel><title>T</title><link>http://localhost</link><item><title>i1</title><link>http://localhost/item1.html</link><description>D</description></item><item><title>i2</title><link>https://localhost/item2.html</link></item></channel></rss>", + "true", + "2", + "<item><title>i1</title><description><div xmlns=\"http://www.w3.org/1999/xhtml\"><p>D</p></div></description><source>http://localhost/item1.html</source><nr>0</nr><readStatus>0</readStatus><updateStatus>0</updateStatus><mark>0</mark><time>1678397817</time><sourceId/><sourceNr>0</sourceNr><attributes/></item>", + "<item><title>i2</title><source>https://localhost/item2.html</source><nr>0</nr><readStatus>0</readStatus><updateStatus>0</updateStatus><mark>0</mark><time>1678397817</time><sourceId/><sourceNr>0</sourceNr><attributes/></item>", + NULL +}; + +/* Test case to prevent | command injection in item link which could trigger + a HTML5 extraction */ +gchar *tc_rss_feed2_rce[] = { + "<rss version=\"2.0\"><channel><title>T</title><item><title>i1</title><link>|date >/tmp/bad-item-link.txt</link></item></channel></rss>", + "true", + "1", + "<item><title>i1</title><nr>0</nr><readStatus>0</readStatus><updateStatus>0</updateStatus><mark>0</mark><time>1678397817</time><sourceId/><sourceNr>0</sourceNr><attributes/></item>", + NULL +}; + +static void +tc_parse_feed (gconstpointer user_data) +{ + gchar **tc = (gchar **)user_data; + nodePtr node; + feedParserCtxtPtr ctxt; + int i; + GList *iter; + + node = node_new (feed_get_node_type ()); + node_set_data (node, feed_new ()); + node_set_subscription (node, subscription_new (NULL, NULL, NULL)); + ctxt = feed_parser_ctxt_new (node->subscription, tc[0], strlen(tc[0])); + + g_assert_cmpstr (feed_parse (ctxt)?"true":"false", ==, tc[1]); + g_assert (g_list_length (ctxt->items) == atoi(tc[2])); + + i = 2; + iter = ctxt->items; + while (tc[++i]) { + gchar *buffer, *tmp, *tmp2; + gint buffersize; + xmlDocPtr doc = xmlNewDoc (BAD_CAST"1.0"); + xmlNodePtr rootNode = xmlNewDocNode (doc, NULL, BAD_CAST"result", NULL); + + xmlDocSetRootElement (doc, rootNode); + + // Force time and delete <timestr> to make result compareable + itemPtr item = (itemPtr)iter->data; + item->time = 1678397817; + item_to_xml (item, rootNode); + + xmlNode *timestr = xpath_find (rootNode, "//timestr"); + if (timestr) { + xmlUnlinkNode (timestr); + xmlFreeNode (timestr); + } + xmlDocDumpMemory(doc, (xmlChar **)&buffer, &buffersize); + + /* strip boilerplate */ + tmp = buffer; + if ((tmp = strstr (tmp, "<result>"))) + tmp += 8; + if ((tmp2 = strstr (tmp, "</result>"))) + *tmp2 = 0; + + g_assert_cmpstr (tc[i], ==, tmp); + + xmlFreeDoc (doc); + xmlFree (buffer); + + iter = g_list_next (iter); + } + + feed_parser_ctxt_free (ctxt); + node_free (node); +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + if (argv[1] && g_str_equal (argv[1], "--debug")) + set_debug_level (DEBUG_UPDATE | DEBUG_HTML | DEBUG_PARSING); + + g_test_add_data_func ("/rss/feed1", &tc_rss_feed1, &tc_parse_feed); + g_test_add_data_func ("/rss/feed2_rce", &tc_rss_feed2_rce, &tc_parse_feed); + + return g_test_run(); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/ui/liferea_shell.c new/liferea-1.14.1/src/ui/liferea_shell.c --- old/liferea-1.14.0/src/ui/liferea_shell.c 2023-01-09 23:24:32.000000000 +0100 +++ new/liferea-1.14.1/src/ui/liferea_shell.c 2023-02-08 21:29:29.000000000 +0100 @@ -1387,7 +1387,6 @@ liferea_shell_update_toolbar (); liferea_shell_update_history_actions (); liferea_shell_setup_URL_receiver (); - liferea_shell_restore_state (overrideWindowState); gtk_widget_set_sensitive (GTK_WIDGET (shell->feedlistViewWidget), TRUE); @@ -1407,6 +1406,7 @@ G_CALLBACK (liferea_shell_update_node_actions), NULL); /* 11.) Restore latest layout and selection */ + liferea_shell_restore_state (overrideWindowState); conf_get_int_value (DEFAULT_VIEW_MODE, &mode); itemview_set_layout (mode); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/update.c new/liferea-1.14.1/src/update.c --- old/liferea-1.14.0/src/update.c 2022-09-16 23:00:11.000000000 +0200 +++ new/liferea-1.14.1/src/update.c 2023-03-09 23:12:30.000000000 +0100 @@ -234,6 +234,13 @@ request->authValue = g_strdup (authValue); } +void +update_request_allow_commands (UpdateRequest *request, gboolean allowCommands) +{ + request->allowCommands = allowCommands; +} + + /* update result object */ updateResultPtr @@ -672,8 +679,14 @@ /* everything starting with '|' is a local command */ if (*(job->request->source) == '|') { - debug1 (DEBUG_UPDATE, "Recognized local command: %s", job->request->source); - update_exec_cmd (job); + if (job->request->allowCommands) { + debug1 (DEBUG_UPDATE, "Recognized local command: %s", job->request->source); + update_exec_cmd (job); + } else { + debug1 (DEBUG_UPDATE, "Refusing to run local command from unexpected source: %s", job->request->source); + job->result->httpstatus = 403; /* Forbidden. */ + update_process_finished_job (job); + } return; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/update.h new/liferea-1.14.1/src/update.h --- old/liferea-1.14.0/src/update.h 2022-03-30 23:38:32.000000000 +0200 +++ new/liferea-1.14.1/src/update.h 2023-03-09 23:12:30.000000000 +0100 @@ -103,6 +103,7 @@ updateOptionsPtr options; /**< Update options for the request */ gchar *filtercmd; /**< Command will filter output of URL */ updateStatePtr updateState; /**< Update state of the requested object (etags, last modified...) */ + gboolean allowCommands; /**< Allow this requests to run commands */ }; /** structure to store results of the processing of an update request */ @@ -229,6 +230,21 @@ void update_request_set_auth_value (UpdateRequest *request, const gchar* authValue); /** + * Allows *this* request to run local commands. + * + * At first it may look this flag should be in updateOptions, but we can + * take a safer path: feed commands are restricted to a few use cases while + * options are propagated to downstream requests (feed enrichment, comments, + * etc.), so it is a good idea to prevent these from running commands in the + * local system via tricky URLs without needing to validate these options + * everywhere (which is error-prone). + * + * @param request the update request + * @param can_run TRUE if the request can run commands, FALSE otherwise. + */ +void update_request_allow_commands (UpdateRequest *request, gboolean allowCommands); + +/** * Creates a new update result for the given update request. * * @returns update result (to be free'd using update_result_free()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/liferea-1.14.0/src/vfolder.c new/liferea-1.14.1/src/vfolder.c --- old/liferea-1.14.0/src/vfolder.c 2023-01-10 20:45:34.000000000 +0100 +++ new/liferea-1.14.1/src/vfolder.c 2023-03-09 23:13:43.000000000 +0100 @@ -308,7 +308,7 @@ NODE_CAPABILITY_SHOW_UNREAD_COUNT | NODE_CAPABILITY_EXPORT_ITEMS, "vfolder", - NULL, + ICON_VFOLDER, vfolder_import, vfolder_export, vfolder_load, @@ -320,7 +320,6 @@ vfolder_properties, vfolder_free }; - nti.icon = icon_get (ICON_VFOLDER); return &nti; }