comparison src/editors.c @ 1478:3cc98d5c6907

Improve editors through .desktop files implementation: - stricter Exec parameters detection - correct Icon key handling (absolute file vs name and --icon prefix) - improved escape, single, double quotes handling and escaping
author zas_
date Thu, 26 Mar 2009 21:49:20 +0000
parents e9f9d3da3f43
children d062522699dc
comparison
equal deleted inserted replaced
1477:29aa897ea540 1478:3cc98d5c6907
142 list = g_list_concat(list, filter_to_list(conv_table[j][1])); 142 list = g_list_concat(list, filter_to_list(conv_table[j][1]));
143 143
144 return list; 144 return list;
145 } 145 }
146 146
147 static gboolean editor_accepts_parameters(EditorDescription *editor)
148 {
149 const gchar *p = editor->exec;
150
151 if (!p) return FALSE;
152
153 while (*p)
154 {
155 if (*p == '%' && p[1])
156 {
157 switch (p[1])
158 {
159 case 'F':
160 case 'f':
161 case 'U':
162 case 'u':
163 case 'i':
164 case 'k':
165 case 'c':
166 return TRUE;
167 default:
168 break;
169 }
170 }
171 p++;
172 }
173
174 return FALSE;
175 }
176
147 static gboolean editor_read_desktop_file(const gchar *path) 177 static gboolean editor_read_desktop_file(const gchar *path)
148 { 178 {
149 GKeyFile *key_file; 179 GKeyFile *key_file;
150 EditorDescription *editor; 180 EditorDescription *editor;
151 gchar *extensions; 181 gchar *extensions;
254 return TRUE; 284 return TRUE;
255 } 285 }
256 286
257 editor->name = g_key_file_get_locale_string(key_file, DESKTOP_GROUP, "Name", NULL, NULL); 287 editor->name = g_key_file_get_locale_string(key_file, DESKTOP_GROUP, "Name", NULL, NULL);
258 editor->icon = g_key_file_get_string(key_file, DESKTOP_GROUP, "Icon", NULL); 288 editor->icon = g_key_file_get_string(key_file, DESKTOP_GROUP, "Icon", NULL);
289
290 /* Icon key can be either a full path (absolute with file name extension) or an icon name (without extension) */
291 if (editor->icon && !g_path_is_absolute(editor->icon))
292 {
293 gchar *ext = strrchr(editor->icon, '.');
294
295 if (ext && strlen(ext) == 4 &&
296 (!strcmp(ext, ".png") || !strcmp(ext, ".xpm") || !strcmp(ext, ".svg")))
297 {
298 log_printf(_("Desktop file '%s' should not include extension in Icon key: '%s'\n"),
299 editor->file, editor->icon);
300
301 // drop extension
302 *ext = '\0';
303 }
304 }
259 305
260 editor->exec = g_key_file_get_string(key_file, DESKTOP_GROUP, "Exec", NULL); 306 editor->exec = g_key_file_get_string(key_file, DESKTOP_GROUP, "Exec", NULL);
261 307
262 /* we take only editors that accept parameters, FIXME: the test can be improved */ 308 /* we take only editors that accept parameters */
263 if (!strchr(editor->exec, '%')) editor->hidden = TRUE; 309 if (!editor_accepts_parameters(editor)) editor->hidden = TRUE;
264 310
265 editor->menu_path = g_key_file_get_string(key_file, DESKTOP_GROUP, "X-Geeqie-Menu-Path", NULL); 311 editor->menu_path = g_key_file_get_string(key_file, DESKTOP_GROUP, "X-Geeqie-Menu-Path", NULL);
266 if (!editor->menu_path) editor->menu_path = g_strdup("EditMenu/ExternalMenu"); 312 if (!editor->menu_path) editor->menu_path = g_strdup("EditMenu/ExternalMenu");
267 313
268 editor->hotkey = g_key_file_get_string(key_file, DESKTOP_GROUP, "X-Geeqie-Hotkey", NULL); 314 editor->hotkey = g_key_file_get_string(key_file, DESKTOP_GROUP, "X-Geeqie-Hotkey", NULL);
269 315
626 else 672 else
627 p = ""; 673 p = "";
628 } 674 }
629 675
630 g_assert(p); 676 g_assert(p);
631 while (*p != '\0') 677 string = g_string_append(string, p);
632 {
633 /* must escape \, ", `, and $ to avoid problems,
634 * we assume system shell supports bash-like escaping
635 */
636 if (strchr("\\\"`$", *p) != NULL)
637 {
638 string = g_string_append_c(string, '\\');
639 }
640 string = g_string_append_c(string, *p);
641 p++;
642 }
643 678
644 if (type == PATH_FILE_URL) g_string_prepend(string, "file://"); 679 if (type == PATH_FILE_URL) g_string_prepend(string, "file://");
645 pathl = path_from_utf8(string->str); 680 pathl = path_from_utf8(string->str);
646 g_string_free(string, TRUE); 681 g_string_free(string, TRUE);
647 682
652 } 687 }
653 688
654 return pathl; 689 return pathl;
655 } 690 }
656 691
692 static GString *append_quoted(GString *str, const char *s, gboolean single_quotes, gboolean double_quotes)
693 {
694 const char *p;
695
696 if (!single_quotes)
697 {
698 if (!double_quotes)
699 g_string_append_c(str, '\'');
700 else
701 g_string_append(str, "\"'");
702 }
703
704 for (p = s; *p != '\0'; p++)
705 {
706 if (*p == '\'')
707 g_string_append(str, "'\\''");
708 else
709 g_string_append_c(str, *p);
710 }
711
712 if (!single_quotes)
713 {
714 if (!double_quotes)
715 g_string_append_c(str, '\'');
716 else
717 g_string_append(str, "'\"");
718 }
719
720 return str;
721 }
722
657 723
658 EditorFlags editor_command_parse(const EditorDescription *editor, GList *list, gchar **output) 724 EditorFlags editor_command_parse(const EditorDescription *editor, GList *list, gchar **output)
659 { 725 {
660 EditorFlags flags = 0; 726 EditorFlags flags = 0;
661 const gchar *p; 727 const gchar *p;
662 GString *result = NULL; 728 GString *result = NULL;
729 gboolean escape = FALSE;
730 gboolean single_quotes = FALSE;
731 gboolean double_quotes = FALSE;
663 732
664 if (output) 733 if (output)
665 result = g_string_new(""); 734 result = g_string_new("");
666 735
667 if (editor->exec[0] == '\0') 736 if (editor->exec[0] == '\0')
676 745
677 /* command */ 746 /* command */
678 747
679 while (*p) 748 while (*p)
680 { 749 {
681 if (*p != '%') 750 if (escape)
682 { 751 {
752 escape = FALSE;
683 if (output) result = g_string_append_c(result, *p); 753 if (output) result = g_string_append_c(result, *p);
684 } 754 }
685 else /* *p == '%' */ 755 else if (*p == '\\')
756 {
757 if (!single_quotes) escape = TRUE;
758 if (output) result = g_string_append_c(result, *p);
759 }
760 else if (*p == '\'')
761 {
762 if (output) result = g_string_append_c(result, *p);
763 if (!single_quotes && !double_quotes)
764 single_quotes = TRUE;
765 else if (single_quotes)
766 single_quotes = FALSE;
767 }
768 else if (*p == '"')
769 {
770 if (output) result = g_string_append_c(result, *p);
771 if (!single_quotes && !double_quotes)
772 double_quotes = TRUE;
773 else if (double_quotes)
774 double_quotes = FALSE;
775 }
776 else if (*p == '%' && p[1])
686 { 777 {
687 gchar *pathl = NULL; 778 gchar *pathl = NULL;
688 779
689 p++; 780 p++;
690 781
714 flags |= EDITOR_ERROR_NO_FILE; 805 flags |= EDITOR_ERROR_NO_FILE;
715 goto err; 806 goto err;
716 } 807 }
717 if (output) 808 if (output)
718 { 809 {
719 result = g_string_append_c(result, '"'); 810 result = append_quoted(result, pathl, single_quotes, double_quotes);
720 result = g_string_append(result, pathl);
721 result = g_string_append_c(result, '"');
722 } 811 }
723 g_free(pathl); 812 g_free(pathl);
724 } 813 }
725 break; 814 break;
726 815
749 838
750 if (output) 839 if (output)
751 { 840 {
752 ok = TRUE; 841 ok = TRUE;
753 if (work != list) g_string_append_c(result, ' '); 842 if (work != list) g_string_append_c(result, ' ');
754 result = g_string_append_c(result, '"'); 843 result = append_quoted(result, pathl, single_quotes, double_quotes);
755 result = g_string_append(result, pathl);
756 result = g_string_append_c(result, '"');
757 } 844 }
758 g_free(pathl); 845 g_free(pathl);
759 } 846 }
760 work = work->next; 847 work = work->next;
761 } 848 }
765 goto err; 852 goto err;
766 } 853 }
767 } 854 }
768 break; 855 break;
769 case 'i': 856 case 'i':
770 if (output) 857 if (editor->icon && *editor->icon)
771 { 858 {
772 result = g_string_append(result, editor->icon); 859 if (output)
860 {
861 result = g_string_append(result, "--icon ");
862 result = append_quoted(result, editor->icon, single_quotes, double_quotes);
863 }
773 } 864 }
774 break; 865 break;
775 case 'c': 866 case 'c':
776 if (output) 867 if (output)
777 { 868 {
778 result = g_string_append(result, editor->name); 869 result = append_quoted(result, editor->name, single_quotes, double_quotes);
779 } 870 }
780 break; 871 break;
781 case 'k': 872 case 'k':
782 if (output) 873 if (output)
783 { 874 {
784 result = g_string_append(result, editor->file); 875 result = append_quoted(result, editor->file, single_quotes, double_quotes);
785 } 876 }
786 break; 877 break;
787 case '%': 878 case '%':
788 /* %% = % escaping */ 879 /* %% = % escaping */
789 if (output) result = g_string_append_c(result, *p); 880 if (output) result = g_string_append_c(result, *p);
799 default: 890 default:
800 flags |= EDITOR_ERROR_SYNTAX; 891 flags |= EDITOR_ERROR_SYNTAX;
801 goto err; 892 goto err;
802 } 893 }
803 } 894 }
895 else
896 {
897 if (output) result = g_string_append_c(result, *p);
898 }
804 p++; 899 p++;
805 } 900 }
806 901
807 if (output) *output = g_string_free(result, FALSE); 902 if (output)
903 {
904 *output = g_string_free(result, FALSE);
905 DEBUG_3("Editor cmd: %s", *output);
906 }
907
808 return flags; 908 return flags;
809 909
810 910
811 err: 911 err:
812 if (output) 912 if (output)