3535#define g_drive_is_removable g_drive_is_media_removable
3636#endif
3737
38+ #ifndef GLIB_VERSION_2_70
39+ #define g_pattern_spec_match g_pattern_match
40+ #endif
41+
3842typedef struct {
3943 SelectionType selection_type ;
4044 gchar * * extensions ;
@@ -58,6 +62,15 @@ typedef struct {
5862 gboolean run_in_terminal ;
5963 gchar * uri_scheme ;
6064
65+ GList * allowed_location_patterns ;
66+ GList * forbidden_location_patterns ;
67+ GList * allowed_location_filenames ;
68+ GList * forbidden_location_filenames ;
69+
70+ GList * allowed_patterns ;
71+ GList * forbidden_patterns ;
72+ GList * allowed_filenames ;
73+ GList * forbidden_filenames ;
6174
6275 gboolean constructing ;
6376} NemoActionPrivate ;
@@ -547,6 +560,51 @@ strip_custom_modifier (const gchar *raw, gboolean *custom, gchar **out)
547560 }
548561}
549562
563+ static void
564+ populate_patterns_and_filenames (NemoAction * action ,
565+ gchar * * array ,
566+ GList * * allowed_patterns ,
567+ GList * * forbidden_patterns ,
568+ GList * * allowed_filenames ,
569+ GList * * forbidden_filenames )
570+ {
571+ * allowed_patterns = NULL ;
572+ * forbidden_patterns = NULL ;
573+ * allowed_filenames = NULL ;
574+ * forbidden_filenames = NULL ;
575+
576+ if (array == NULL ) {
577+ return ;
578+ }
579+
580+ gint i ;
581+
582+ for (i = 0 ; i < g_strv_length (array ); i ++ ) {
583+ const gchar * str = array [i ];
584+
585+ if (g_strstr_len (str , -1 , "?" ) || g_strstr_len (str , -1 , "*" )) {
586+ if (g_str_has_prefix (array [i ], "!" )) {
587+ * forbidden_patterns = g_list_prepend (* forbidden_patterns , g_pattern_spec_new (array [i ] + 1 ));
588+ } else {
589+ * allowed_patterns = g_list_prepend (* allowed_patterns , g_pattern_spec_new (array [i ]));
590+ }
591+
592+ continue ;
593+ }
594+
595+ if (g_str_has_prefix (array [i ], "!" )) {
596+ * forbidden_filenames = g_list_prepend (* forbidden_filenames , g_strdup (array [i ] + 1 ));
597+ } else {
598+ * allowed_filenames = g_list_prepend (* allowed_filenames , g_strdup (array [i ]));
599+ }
600+ }
601+
602+ * allowed_patterns = g_list_reverse (* allowed_patterns );
603+ * forbidden_patterns = g_list_reverse (* forbidden_patterns );
604+ * allowed_filenames = g_list_reverse (* allowed_filenames );
605+ * forbidden_filenames = g_list_reverse (* forbidden_filenames );
606+ }
607+
550608void
551609nemo_action_constructed (GObject * object )
552610{
@@ -679,6 +737,32 @@ nemo_action_constructed (GObject *object)
679737 KEY_TERMINAL ,
680738 NULL );
681739
740+ gchar * * locations = g_key_file_get_string_list (key_file ,
741+ ACTION_FILE_GROUP ,
742+ KEY_LOCATIONS ,
743+ NULL ,
744+ NULL );
745+
746+ populate_patterns_and_filenames (action , locations ,
747+ & priv -> allowed_location_patterns ,
748+ & priv -> forbidden_location_patterns ,
749+ & priv -> allowed_location_filenames ,
750+ & priv -> forbidden_location_filenames );
751+ g_strfreev (locations );
752+
753+ gchar * * files = g_key_file_get_string_list (key_file ,
754+ ACTION_FILE_GROUP ,
755+ KEY_FILES ,
756+ NULL ,
757+ NULL );
758+
759+ populate_patterns_and_filenames (action , files ,
760+ & priv -> allowed_patterns ,
761+ & priv -> forbidden_patterns ,
762+ & priv -> allowed_filenames ,
763+ & priv -> forbidden_filenames );
764+ g_strfreev (files );
765+
682766 gboolean is_desktop = FALSE;
683767
684768 if (conditions && condition_count > 0 ) {
@@ -907,6 +991,14 @@ nemo_action_finalize (GObject *object)
907991 g_list_free_full (priv -> dbus , (GDestroyNotify ) dbus_condition_free );
908992 g_list_free_full (priv -> gsettings , (GDestroyNotify ) gsettings_condition_free );
909993
994+ g_list_free_full (priv -> allowed_location_patterns , (GDestroyNotify ) g_pattern_spec_free );
995+ g_list_free_full (priv -> forbidden_location_patterns , (GDestroyNotify ) g_pattern_spec_free );
996+ g_list_free_full (priv -> allowed_patterns , (GDestroyNotify ) g_pattern_spec_free );
997+ g_list_free_full (priv -> forbidden_patterns , (GDestroyNotify ) g_pattern_spec_free );
998+ g_list_free_full (priv -> allowed_location_filenames , (GDestroyNotify ) g_free );
999+ g_list_free_full (priv -> forbidden_location_filenames , (GDestroyNotify ) g_free );
1000+ g_list_free_full (priv -> allowed_filenames , (GDestroyNotify ) g_free );
1001+ g_list_free_full (priv -> forbidden_filenames , (GDestroyNotify ) g_free );
9101002
9111003 g_clear_handle_id (& priv -> dbus_recalc_timeout_id , g_source_remove );
9121004 g_clear_handle_id (& priv -> gsettings_recalc_timeout_id , g_source_remove );
@@ -1548,7 +1640,113 @@ get_is_dir (NemoFile *file)
15481640 return ret ;
15491641}
15501642
1643+ static gboolean
1644+ check_is_allowed (NemoAction * action ,
1645+ NemoFile * parent ,
1646+ GList * selection ,
1647+ GList * allowed_patterns ,
1648+ GList * forbidden_patterns ,
1649+ GList * allowed_names ,
1650+ GList * forbidden_names )
15511651{
1652+ // If there are no pattern/name specs, always allow the location..
1653+ if ((allowed_patterns == NULL && forbidden_patterns == NULL && allowed_names == NULL && forbidden_names == NULL )) {
1654+ return TRUE;
1655+ }
1656+
1657+ GList * l , * files ;
1658+
1659+ if (parent != NULL ) {
1660+ DEBUG ("Checking pattern/name matching for location: %s" , nemo_file_peek_name (parent ));
1661+ files = g_list_prepend (NULL , parent );
1662+ }
1663+ else {
1664+ DEBUG ("Checking pattern/name matching for selected files" );
1665+ files = selection ;
1666+ }
1667+
1668+ gboolean allowed = TRUE;
1669+
1670+ for (l = files ; l != NULL ; l = l -> next ) {
1671+ NemoFile * file = NEMO_FILE (l -> data );
1672+
1673+ g_autofree gchar * path = nemo_file_get_path (file );
1674+ // If the first file (or the single parent) isn't native, no need to
1675+ // check all selected items, just exit early.
1676+ if (path == NULL ) {
1677+ goto check_allowed_done ;
1678+ }
1679+
1680+ const gchar * name = nemo_file_peek_name (file );
1681+ gboolean allowed_allowed = TRUE;
1682+ gboolean forbidden_allowed = TRUE;
1683+ GList * ll ;
1684+
1685+ if (allowed_patterns != NULL || allowed_names != NULL ) {
1686+ allowed_allowed = FALSE;
1687+
1688+ for (ll = allowed_patterns ; ll != NULL ; ll = ll -> next ) {
1689+ if (g_pattern_spec_match ((GPatternSpec * ) ll -> data , strlen (name ), name , NULL )) {
1690+ allowed_allowed = TRUE;
1691+ break ;
1692+ }
1693+ }
1694+
1695+ for (ll = allowed_names ; ll != NULL ; ll = ll -> next ) {
1696+ gchar * aname = (gchar * ) ll -> data ;
1697+
1698+ if (name [0 ] == '/' && g_strcmp0 (path , aname ) == 0 ) {
1699+ allowed_allowed = TRUE;
1700+ break ;
1701+ }
1702+ else
1703+ if (g_str_has_suffix (name , aname )) {
1704+ allowed_allowed = TRUE;
1705+ break ;
1706+ }
1707+ }
1708+ }
1709+
1710+ if (forbidden_patterns != NULL || forbidden_names != NULL ) {
1711+ // (forbidden_allowed = TRUE;)
1712+
1713+ for (ll = forbidden_patterns ; ll != NULL ; ll = ll -> next ) {
1714+ if (g_pattern_spec_match ((GPatternSpec * ) ll -> data , strlen (name ), name , NULL )) {
1715+ forbidden_allowed = FALSE;
1716+ break ;
1717+ }
1718+ }
1719+
1720+ for (ll = forbidden_names ; ll != NULL ; ll = ll -> next ) {
1721+ gchar * fname = (gchar * ) ll -> data ;
1722+ if (name [0 ] == '/' && g_strcmp0 (path , fname ) == 0 ) {
1723+ forbidden_allowed = FALSE;
1724+ break ;
1725+ }
1726+ else
1727+ if (g_str_has_suffix (name , fname )) {
1728+ forbidden_allowed = FALSE;
1729+ break ;
1730+ }
1731+ }
1732+ }
1733+
1734+ DEBUG ("Final result - allowed pass: %d, forbidden pass: %d" , allowed_allowed , forbidden_allowed );
1735+ if (!(allowed_allowed && forbidden_allowed )) {
1736+ allowed = FALSE;
1737+ break ;
1738+ }
1739+ }
1740+
1741+ check_allowed_done :
1742+ if (parent != NULL ) {
1743+ g_list_free (files );
1744+ }
1745+
1746+ return allowed ;
1747+ }
1748+
1749+
15521750static gboolean
15531751get_visibility (NemoAction * action ,
15541752 GList * selection ,
@@ -1568,6 +1766,19 @@ get_visibility (NemoAction *action,
15681766 return FALSE;
15691767 }
15701768
1769+ if (!check_is_allowed (action , parent , NULL ,
1770+ priv -> allowed_location_patterns ,
1771+ priv -> forbidden_location_patterns ,
1772+ priv -> allowed_location_filenames ,
1773+ priv -> forbidden_location_filenames )) {
1774+ return FALSE;
1775+ }
1776+
1777+ if (!check_is_allowed (action , NULL , selection ,
1778+ priv -> allowed_patterns ,
1779+ priv -> forbidden_patterns ,
1780+ priv -> allowed_filenames ,
1781+ priv -> forbidden_filenames )) {
15711782 return FALSE;
15721783 }
15731784
0 commit comments