00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <locale.h>
00029 #include <libintl.h>
00030
00031
00032 #include "gxsm_app.h"
00033
00034 #include "glbvars.h"
00035
00036 #include "surface.h"
00037
00038 #include <errno.h>
00039 #include <sys/types.h>
00040 #include <sys/wait.h>
00041 #include <libgnomevfs/gnome-vfs-uri.h>
00042
00043 enum {
00044 TARGET_URI_LIST,
00045 TARGET_URL
00046 };
00047
00048
00049
00050
00051
00052
00053
00054 typedef struct {
00055 gchar *name;
00056 gint pid;
00057 } ChildData;
00058
00059 static char *download_dir = NULL;
00060
00061
00062
00063
00064
00065
00066
00067
00068 gboolean App::input_func(GIOChannel *source, GIOCondition condition, gpointer data)
00069 {
00070 char buf[2];
00071 ChildData *child_data = (ChildData*)data;
00072 int status;
00073
00074 if (read (g_io_channel_unix_get_fd(source), buf, 2) != 2 ||
00075 (buf[0] != 'O') || (buf[1] != 'K'))
00076 {
00077 g_warning ("Download failed!\n");
00078 }
00079 else
00080 {
00081 gapp->xsm->load (child_data->name);
00082 }
00083
00084 waitpid (child_data->pid, &status, 0);
00085
00086 g_free (child_data->name);
00087 g_free (child_data);
00088
00089 close(g_io_channel_unix_get_fd(source));
00090
00091 return FALSE;
00092 }
00093
00094 void App::grab_url(const gchar *name)
00095 {
00096 int pid;
00097 int fds[2];
00098
00099 if (!download_dir)
00100 {
00101 int fd;
00102 #define GXSMTMPPREFIX "/tmp/GxsmTmp"
00103 char *buffer = g_strdup(GXSMTMPPREFIX"_XXXXXX");
00104
00105 if (!(fd=mkstemp(buffer)) )
00106 {
00107 g_warning ("Could not generate temporary directory: %s\n",
00108 g_strerror(errno));
00109 return;
00110 }
00111 close(fd);
00112 FILE *cmd = popen("rm -rf " GXSMTMPPREFIX "*", "w");
00113 if(cmd)
00114 pclose(cmd);
00115
00116 if ((mkdir(buffer, 0755) != 0))
00117 {
00118 g_warning ("Could not generate temporary directory: %s\n",
00119 g_strerror(errno));
00120 return;
00121 }
00122
00123 download_dir = buffer;
00124 }
00125
00126 if (pipe(fds))
00127 {
00128 g_warning ("Could not create pipe: %s\n", g_strerror(errno));
00129 return;
00130 }
00131
00132 if (!(pid = fork()))
00133 {
00134
00135
00136 close(fds[0]);
00137
00138
00139
00140 if (!(pid = fork()))
00141 {
00142 execlp("wget", "wget", "-q", "-P", download_dir, name, NULL);
00143 g_warning("Could not run wget: %s\n", g_strerror(errno));
00144 _exit(0);
00145 }
00146 else if (pid > 0)
00147 {
00148 int status;
00149 waitpid (pid, &status, 0);
00150
00151 if (!status)
00152 write (fds[1], "OK", 2);
00153
00154 _exit(0);
00155 }
00156 else
00157 {
00158 g_warning ("Could not fork!\n");
00159 _exit(0);
00160 }
00161 }
00162 else if (pid > 0)
00163 {
00164
00165
00166 char *tail;
00167 ChildData *child_data;
00168 GIOChannel *ioc;
00169
00170 close(fds[1]);
00171
00172 tail = strrchr(name, '/');
00173 child_data = g_new0 (ChildData, 1);
00174
00175 if (tail)
00176 child_data->name = g_strconcat (download_dir, "/", ++tail, NULL);
00177 else
00178 child_data->name = g_strconcat (download_dir, "/", name, NULL);
00179
00180 child_data->pid = pid;
00181
00182 ioc = g_io_channel_unix_new (fds[0]);
00183 g_io_add_watch(ioc, (GIOCondition)(G_IO_IN|G_IO_HUP|G_IO_NVAL), input_func, child_data);
00184 g_io_channel_unref(ioc);
00185 }
00186 else
00187 g_warning ("Could not fork\n");
00188 }
00189
00190 void App::process_one_filename (GtkWidget * widget, const gchar *filename)
00191 {
00192 int ch = (long) gtk_object_get_data (GTK_OBJECT (widget), "ChNo");
00193 if(ch){
00194 if(ch>0 && ch <= MAX_CHANNELS)
00195 gapp->xsm->ActivateChannel( ch-1 );
00196 }else
00197 if(gapp->xsm->ActivateFreeChannel())
00198 return;
00199
00200 if (strncmp (filename, "http://", 7) == 0)
00201 grab_url (filename);
00202 else
00203 gapp->xsm->load (filename);
00204 }
00205
00206 void App::filenames_dropped(GtkWidget * widget,
00207 GdkDragContext *context,
00208 gint x,
00209 gint y,
00210 GtkSelectionData *selection_data,
00211 guint info,
00212 guint time)
00213 {
00214 if (!selection_data->data)
00215 return;
00216
00217 switch (info){
00218 case TARGET_URI_LIST:
00219 {
00220 GList *names = gnome_vfs_uri_list_parse ((char *)selection_data->data);
00221 if (!names)
00222 return;
00223
00224 for (; names; names = names->next){
00225 const gchar *filename = gnome_vfs_uri_get_path ((const GnomeVFSURI *)names->data);
00226 process_one_filename (widget, filename);
00227 }
00228 gnome_vfs_uri_list_free (names);
00229 break;
00230 }
00231 case TARGET_URL:
00232 gchar *url = g_strdup ((gchar *)selection_data->data);
00233 gchar *p;
00234 if ((p=strchr (url, '\n')) != NULL)
00235 *p = 0;
00236 process_one_filename (widget, url);
00237 g_free (url);
00238 break;
00239 }
00240 }
00241
00242 void
00243 App::configure_drop_on_widget(GtkWidget * widget)
00244 {
00245 static GtkTargetEntry drag_types[] =
00246 {
00247 { "text/uri-list", 0, TARGET_URI_LIST },
00248 { "_NETSCAPE_URL", 0, TARGET_URL }
00249 };
00250 static gint n_drag_types = sizeof(drag_types)/sizeof(drag_types[0]);
00251
00252 gtk_drag_dest_set
00253 ( widget,
00254 (GtkDestDefaults)(
00255 GTK_DEST_DEFAULT_MOTION |
00256 GTK_DEST_DEFAULT_HIGHLIGHT |
00257 GTK_DEST_DEFAULT_DROP
00258 ),
00259 drag_types,
00260 n_drag_types,
00261 GDK_ACTION_COPY
00262 );
00263
00264 gtk_signal_connect(GTK_OBJECT(widget), "drag_data_received",
00265 GTK_SIGNAL_FUNC(filenames_dropped), NULL);
00266 }
00267
00268 void App::drag_data_get (GtkWidget *widget,
00269 GdkDragContext *context,
00270 GtkSelectionData *selection_data,
00271 guint info,
00272 guint time)
00273 {
00274 gchar *file=NULL;
00275 gchar *uri_list;
00276
00277
00278
00279 if (file)
00280 {
00281 uri_list = g_strconcat ("file:", file, NULL);
00282 gtk_selection_data_set (selection_data,
00283 selection_data->target, 8,
00284 (const guchar*)uri_list,
00285 (int)strlen(uri_list));
00286 g_free (uri_list);
00287 }
00288 else
00289 {
00290 gtk_selection_data_set (selection_data,
00291 selection_data->target, 8,
00292 NULL, 0);
00293 }
00294 }
00295
00296 void
00297 App::configure_drag_on_widget(GtkWidget * widget)
00298 {
00299 static GtkTargetEntry drag_types[] =
00300 {
00301 { "text/uri-list", 0, TARGET_URI_LIST }
00302 };
00303 static gint n_drag_types = sizeof(drag_types)/sizeof(drag_types[0]);
00304
00305 gtk_drag_source_set (widget,
00306 GDK_BUTTON1_MASK,
00307 drag_types, n_drag_types,
00308 GDK_ACTION_COPY);
00309
00310 gtk_signal_connect(GTK_OBJECT(widget), "drag_data_get",
00311 GTK_SIGNAL_FUNC(drag_data_get), NULL);
00312 }
00313