12646273f4ed77ef4ec52efea4910d9e201a93f5
[dana/obconf.git] / src / archive.c
1 #include "theme.h"
2 #include "main.h"
3 #include "gettext.h"
4
5 #include <string.h>
6 #include <errno.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10
11 #define gtk_msg(type, args...) \
12 {                                                                        \
13     GtkWidget *msgw;                                                     \
14     msgw = gtk_message_dialog_new(GTK_WINDOW(mainwin),                   \
15                                   GTK_DIALOG_DESTROY_WITH_PARENT |       \
16                                   GTK_DIALOG_MODAL,                      \
17                                   type,                                  \
18                                   GTK_BUTTONS_OK,                        \
19                                   args);                                 \
20     gtk_dialog_run(GTK_DIALOG(msgw));                                    \
21     gtk_widget_destroy(msgw);                                            \
22 }
23
24 static gchar *get_theme_dir();
25 static gboolean change_dir(const gchar *dir);
26 static gchar* name_from_dir(const gchar *dir);
27 static gchar* install_theme_to(const gchar *file, const gchar *to);
28 static gboolean create_theme_archive(const gchar *dir, const gchar *name,
29                                      const gchar *to);
30
31 gchar* archive_install(const gchar *path)
32 {
33     gchar *dest;
34     gchar *name;
35
36     if (!(dest = get_theme_dir()))
37         return NULL;
38
39     if ((name = install_theme_to(path, dest))) {
40         gtk_msg(GTK_MESSAGE_INFO, _("\"%s\" was installed to %s"), name, dest);
41     }
42
43     g_free(dest);
44
45     return name;
46 }
47
48 void archive_create(const gchar *path)
49 {
50     gchar *name;
51     gchar *dest;
52
53     if (!(name = name_from_dir(path)))
54         return;
55
56     {
57         gchar *file;
58         file = g_strdup_printf("%s.obt", name);
59         dest = g_build_path(G_DIR_SEPARATOR_S,
60                             g_get_current_dir(), file, NULL);
61         g_free(file);
62     }
63
64     if (create_theme_archive(path, name, dest))
65         gtk_msg(GTK_MESSAGE_INFO, _("\"%s\" was successfully created"),
66                 dest);
67
68     g_free(dest);
69     g_free(name);
70 }
71
72 static gboolean create_theme_archive(const gchar *dir, const gchar *name,
73                                      const gchar *to)
74 {
75     gchar *glob;
76     gchar **argv;
77     gchar *errtxt = NULL;
78     gchar *parentdir;
79     gint exitcode;
80     GError *e = NULL;
81
82     glob = g_strdup_printf("%s/openbox-3/", name);
83
84     parentdir = g_build_path(G_DIR_SEPARATOR_S, dir, "..", NULL);
85
86     argv = g_new(gchar*, 9);
87     argv[0] = g_strdup("tar");
88     argv[1] = g_strdup("-c");
89     argv[2] = g_strdup("-z");
90     argv[3] = g_strdup("-f");
91     argv[4] = g_strdup(to);
92     argv[5] = g_strdup("-C");
93     argv[6] = g_strdup(parentdir);
94     argv[7] = g_strdup(glob);
95     argv[8] = NULL;
96     if (g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
97                      NULL, &errtxt, &exitcode, &e))
98     {
99         if (exitcode != EXIT_SUCCESS)
100             gtk_msg(GTK_MESSAGE_ERROR,
101                     _("Unable to create the theme archive \"%s\".\nThe following errors were reported:\n%s"),
102                     to, errtxt);
103
104     }
105     else
106         gtk_msg(GTK_MESSAGE_ERROR, _("Unable to run the \"tar\" command: %s"),
107                 e->message);
108
109     g_strfreev(argv);
110     if (e) g_error_free(e);
111     g_free(errtxt);
112     g_free(parentdir);
113     g_free(glob);
114     return exitcode == EXIT_SUCCESS;
115 }
116
117 static gchar *get_theme_dir()
118 {
119     gchar *dir;
120     gint r;
121
122     dir = g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), ".themes", NULL);
123     r = mkdir(dir, 0777);
124     if (r == -1 && errno != EEXIST) {
125         gtk_msg(GTK_MESSAGE_ERROR,
126                 _("Unable to create directory \"%s\": %s"),
127                 dir, strerror(errno));
128         g_free(dir);
129         dir = NULL;
130     }
131
132     return dir;
133 }
134
135 static gchar* name_from_dir(const gchar *dir)
136 {
137     gchar *rc;
138     struct stat st;
139     gboolean r;
140
141     rc = g_build_path(G_DIR_SEPARATOR_S, dir, "openbox-3", "themerc", NULL);
142
143     r = (stat(rc, &st) == 0 && S_ISREG(st.st_mode));
144     g_free(rc);
145
146     if (!r) {
147         gtk_msg(GTK_MESSAGE_ERROR,
148                 _("\"%s\" does not appear to be a valid Openbox theme directory"),
149                 dir);
150         return NULL;
151     }
152     return g_path_get_basename(dir);
153 }
154
155 static gboolean change_dir(const gchar *dir)
156 {
157     if (chdir(dir) == -1) {
158         gtk_msg(GTK_MESSAGE_ERROR, _("Unable to move to directory \"%s\": %s"),
159                 dir, strerror(errno));
160         return FALSE;
161     }
162     return TRUE;
163 }
164
165 static gchar* install_theme_to(const gchar *file, const gchar *to)
166 {
167     gchar **argv;
168     gchar *errtxt = NULL, *outtxt = NULL;
169     gint exitcode;
170     GError *e = NULL;
171     gchar *name = NULL;
172
173     argv = g_new(gchar*, 11);
174     argv[0] = g_strdup("tar");
175     argv[1] = g_strdup("-x");
176     argv[2] = g_strdup("-v");
177     argv[3] = g_strdup("-z");
178     argv[4] = g_strdup("--wildcards");
179     argv[5] = g_strdup("-f");
180     argv[6] = g_strdup(file);
181     argv[7] = g_strdup("-C");
182     argv[8] = g_strdup(to);
183     argv[9] = g_strdup("*/openbox-3/");
184     argv[10] = NULL;
185     if (!g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
186                       &outtxt, &errtxt, &exitcode, &e))
187         gtk_msg(GTK_MESSAGE_ERROR, _("Unable to run the \"tar\" command: %s"),
188                 e->message);
189     g_strfreev(argv);
190     if (e) g_error_free(e);
191
192     if (exitcode != EXIT_SUCCESS)
193         gtk_msg(GTK_MESSAGE_ERROR,
194                 _("Unable to extract the file \"%s\".\nPlease ensure that \"%s\" is writable and that the file is a valid Openbox theme archive.\nThe following errors were reported:\n%s"),
195                 file, to, errtxt);
196
197     if (exitcode == EXIT_SUCCESS) {
198         gchar **lines = g_strsplit(outtxt, "\n", 0);
199         gchar **it;
200         for (it = lines; *it; ++it) {
201             gchar *l = *it;
202             gboolean found = FALSE;
203
204             while (*l && !found) {
205                 if (!strcmp(l, "/openbox-3/")) {
206                     *l = '\0'; /* cut the string */
207                     found = TRUE;
208                 }
209                 ++l;
210             }
211
212             if (found) {
213                 name = g_strdup(*it);
214                 break;
215             }
216         }
217         g_strfreev(lines);
218     }
219
220     g_free(outtxt);
221     g_free(errtxt);
222     return name;
223 }