/* * Run default action of specified file. * Full path of the file is required by this function. */ gboolean vfs_file_info_open_file( VFSFileInfo* fi, const char* file_path, GError** err ) { VFSMimeType * mime_type; char* app_name; VFSAppDesktop* app; GList* files = NULL; gboolean ret = FALSE; char* argv[ 2 ]; if ( vfs_file_info_is_executable( fi, file_path ) ) { argv[ 0 ] = (char *) file_path; argv[ 1 ] = '\0'; ret = g_spawn_async( NULL, argv, NULL, G_SPAWN_STDOUT_TO_DEV_NULL| G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, err ); } else { mime_type = vfs_file_info_get_mime_type( fi ); app_name = vfs_mime_type_get_default_action( mime_type ); if ( app_name ) { app = vfs_app_desktop_new( app_name ); if ( ! vfs_app_desktop_get_exec( app ) ) app->exec = g_strdup( app_name ); /* FIXME: app->exec */ files = g_list_prepend( files, (gpointer) file_path ); /* FIXME: working dir is needed */ ret = vfs_app_desktop_open_files( gdk_screen_get_default(), NULL, app, files, err ); g_list_free( files ); vfs_app_desktop_unref( app ); g_free( app_name ); } vfs_mime_type_unref( mime_type ); } return ret; }
/* * Parse Exec command line of app desktop file, and translate * it into a real command which can be passed to g_spawn_command_line_async(). * file_list is a null-terminated file list containing full * paths of the files passed to app. * returned char* should be freed when no longer needed. */ static char* translate_app_exec_to_command_line( VFSAppDesktop* app, GList* file_list ) { const char* pexec = vfs_app_desktop_get_exec( app ); char* file; GList* l; gchar *tmp; GString* cmd = g_string_new(""); gboolean add_files = FALSE; for( ; *pexec; ++pexec ) { if( *pexec == '%' ) { ++pexec; switch( *pexec ) { case 'U': for( l = file_list; l; l = l->next ) { tmp = g_filename_to_uri( (char*)l->data, NULL, NULL ); file = g_shell_quote( tmp ); g_free( tmp ); g_string_append( cmd, file ); g_string_append_c( cmd, ' ' ); g_free( file ); } add_files = TRUE; break; case 'u': if( file_list && file_list->data ) { file = (char*)file_list->data; tmp = g_filename_to_uri( file, NULL, NULL ); file = g_shell_quote( tmp ); g_free( tmp ); g_string_append( cmd, file ); g_free( file ); add_files = TRUE; } break; case 'F': case 'N': for( l = file_list; l; l = l->next ) { file = (char*)l->data; tmp = g_shell_quote( file ); g_string_append( cmd, tmp ); g_string_append_c( cmd, ' ' ); g_free( tmp ); } add_files = TRUE; break; case 'f': case 'n': if( file_list && file_list->data ) { file = (char*)file_list->data; tmp = g_shell_quote( file ); g_string_append( cmd, tmp ); g_free( tmp ); add_files = TRUE; } break; case 'D': for( l = file_list; l; l = l->next ) { tmp = g_path_get_dirname( (char*)l->data ); file = g_shell_quote( tmp ); g_free( tmp ); g_string_append( cmd, file ); g_string_append_c( cmd, ' ' ); g_free( file ); } add_files = TRUE; break; case 'd': if( file_list && file_list->data ) { tmp = g_path_get_dirname( (char*)file_list->data ); file = g_shell_quote( tmp ); g_free( tmp ); g_string_append( cmd, file ); g_free( tmp ); add_files = TRUE; } break; case 'c': g_string_append( cmd, vfs_app_desktop_get_disp_name( app ) ); break; case 'i': /* Add icon name */ if( vfs_app_desktop_get_icon_name( app ) ) { g_string_append( cmd, "--icon " ); g_string_append( cmd, vfs_app_desktop_get_icon_name( app ) ); } break; case 'k': /* Location of the desktop file */ break; case 'v': /* Device name */ break; case '%': g_string_append_c ( cmd, '%' ); break; case '\0': goto _finish; break; } } else /* not % escaped part */ { g_string_append_c ( cmd, *pexec ); } } _finish: if( ! add_files ) { g_string_append_c ( cmd, ' ' ); for( l = file_list; l; l = l->next ) { file = (char*)l->data; tmp = g_shell_quote( file ); g_string_append( cmd, tmp ); g_string_append_c( cmd, ' ' ); g_free( tmp ); } } return g_string_free( cmd, FALSE ); }
gboolean vfs_app_desktop_open_files( GdkScreen* screen, const char* working_dir, VFSAppDesktop* app, GList* file_paths, GError** err ) { char* exec = NULL; char* cmd; GList* l; gchar** argv = NULL; gint argc = 0; const char* sn_desc; if( vfs_app_desktop_get_exec( app ) ) { if ( ! strchr( vfs_app_desktop_get_exec( app ), '%' ) ) { /* No filename parameters */ exec = g_strconcat( vfs_app_desktop_get_exec( app ), " %f", NULL ); } else { exec = g_strdup( vfs_app_desktop_get_exec( app ) ); } } if ( exec ) { if( !screen ) screen = gdk_screen_get_default(); sn_desc = vfs_app_desktop_get_disp_name( app ); if( !sn_desc ) sn_desc = exec; if( vfs_app_desktop_open_multiple_files( app ) ) { cmd = translate_app_exec_to_command_line( app, file_paths ); if ( cmd ) { if ( vfs_app_desktop_open_in_terminal( app ) ) exec_in_terminal( sn_desc, app->path && app->path[0] ? app->path : working_dir, cmd ); else { /* g_debug( "Execute %s\n", cmd ); */ if( g_shell_parse_argv( cmd, &argc, &argv, NULL ) ) { vfs_exec_on_screen( screen, app->path && app->path[0] ? app->path : working_dir, argv, NULL, sn_desc, VFS_EXEC_DEFAULT_FLAGS, err ); g_strfreev( argv ); } } g_free( cmd ); } } else { // app does not accept multiple files, so run multiple times GList* single; l = file_paths; do { if ( l ) { // just pass a single file path to translate single = g_list_append( NULL, l->data ); } else { // there are no files being passed, just run once single = NULL; } cmd = translate_app_exec_to_command_line( app, single ); g_list_free( single ); if ( cmd ) { if ( vfs_app_desktop_open_in_terminal( app ) ) exec_in_terminal( sn_desc, app->path && app->path[0] ? app->path : working_dir, cmd ); else { /* g_debug( "Execute %s\n", cmd ); */ if( g_shell_parse_argv( cmd, &argc, &argv, NULL ) ) { vfs_exec_on_screen( screen, app->path && app->path[0] ? app->path : working_dir, argv, NULL, sn_desc, G_SPAWN_SEARCH_PATH| G_SPAWN_STDOUT_TO_DEV_NULL| G_SPAWN_STDERR_TO_DEV_NULL, err ); g_strfreev( argv ); } } g_free( cmd ); } } while ( l = l ? l->next : NULL ); } g_free( exec ); return TRUE; } g_set_error( err, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, _("Command not found") ); return FALSE; }