ctb_actions.c

Go to the documentation of this file.
00001 /*
00002  * File Name: actions.c
00003  */
00004 
00005 /*
00006  * This file is part of ctb.
00007  *
00008  * ctb is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * ctb is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 #include "config.h"
00032 
00033 #include <stdlib.h>
00034 
00035 #include "ctb_log.h"
00036 #include "ctb_actions.h"
00037 #include "filetypes.h"
00038 #include "i18n.h"
00039 #include "ipc.h"
00040 #include "shortcut.h"
00041 #include "fileview.h"
00042 
00043 static void set_special_viewmode(const filelist_entry_t *item,
00044                                  ViewMode mode)
00045 {
00046     fileview_stop_update_display();
00047     filemodel_set_viewmode2(mode);
00048     fileview_dir_down(item->directory_path->str, item->filename->str);
00049 }
00050 
00051 
00052 static void handle_special_item(const filelist_entry_t *item)
00053 {
00054     const gchar *filename = item->filename->str;
00055     if (strcmp(filename, SPECIAL_BOOKS) == 0) {
00056         set_special_viewmode(item, BOOKS_VIEW);
00057     } else if (strcmp(filename, SPECIAL_IMAGES) == 0) {
00058         set_special_viewmode(item, IMAGES_VIEW);
00059     } else if (strcmp(filename, SPECIAL_NEWS) == 0) {
00060         set_special_viewmode(item, NEWS_VIEW);
00061     } else if (strcmp(filename, SPECIAL_DIR) == 0) {
00062         set_special_viewmode(item, DIR_VIEW);
00063     } else if (strcmp(filename, SPECIAL_SHORTCUTS) == 0) {
00064         set_special_viewmode(item, SHORTCUT_VIEW);
00065     } else if (strcmp(filename, SPECIAL_NOTES) == 0) {
00066         set_special_viewmode(item, NOTES_VIEW);
00067     } else if (strcmp(filename, SPECIAL_SETTINGS) == 0) {
00068         set_special_viewmode(item, SETTINGS_VIEW);
00069     } else if (strcmp(filename, SPECIAL_HELP) == 0) {
00070         set_special_viewmode(item, HELP_VIEW);
00071     } else if (strcmp(filename, SPECIAL_PERSONAL) == 0) {
00072         set_special_viewmode(item, PERSONAL_VIEW);
00073     } else if (strcmp(filename, SPECIAL_RECENT) == 0) {
00074         set_special_viewmode(item, RECENT_VIEW);
00075     } else if (strcmp(filename, SPECIAL_UPDIR) == 0) {
00076         fileview_stop_update_display();
00077         fileview_dir_up();
00078     } else if (strcmp(filename, SPECIAL_SEARCH) == 0) {
00079         fileview_show_search_dialog();
00080     } else {
00081         ERRORPRINTF("unknown special entry '%s'", filename);
00082         g_assert(0);
00083     }
00084 }
00085 
00086 
00087 // activate: launch URL as specified in link shortcut
00088 static int activate_shortcut_to_web_location ( const filelist_entry_t  *fileinfo,
00089                                                const char* url)
00090 {
00091     g_assert(url && url[0]);
00092 
00093     LOGPRINTF( "entry: filename [%s] url [%s]", fileinfo->filename->str, url);
00094     
00095     const gchar *filename_display = fileinfo->filename_display->str;
00096     gchar *ret_message = NULL;
00097     gint errcode = ipc_sys_open_url(url, filename_display, NULL, &ret_message);
00098     
00099     if ( errcode > 0 )
00100     {
00101         gchar *error_msg = NULL;
00102         ERRORPRINTF("cannot open url, url [%s], errcode %d [%s]", url, errcode, ret_message);
00103         switch (errcode)
00104         {
00105         case 1: // url cannot be opened
00106         default:
00107             error_msg = g_strdup_printf(
00108                 _("The webpage '%s' cannot be opened."), url);
00109             show_error_dialog(error_msg);
00110             break;
00111         case 4: // browser failed to open url (may be handled above with custom message)
00112             error_msg = g_strdup_printf(
00113                 _("The webpage '%s' cannot be opened."), url);
00114             show_error_dialog(error_msg);
00115             break;
00116         case 2: // timeout waiting for application window
00117         case 3: // application has exited before creating a window
00118             break;
00119         }
00120         g_free(error_msg);
00121     }
00122 
00123     g_free(ret_message);
00124     return ER_OK;
00125 }
00126 
00127 
00128 static int activate_shortcut_to_application(const filelist_entry_t *fileinfo, const char* cmdline)
00129 {
00130     const gchar *filename_display = fileinfo->filename_display->str;
00131     const gchar *directory        = fileinfo->directory_path->str;
00132 
00133     gchar *ret_message = NULL;
00134     gint errcode = ipc_sys_start_task(cmdline, directory, filename_display, NULL, &ret_message);
00135     if (errcode > 0) {
00136         if (ret_message && ret_message[0] != '\0') {
00137             ERRORPRINTF("cannot launch viewer, cmd_line [%s], errcode %d [%s]", cmdline, errcode, ret_message);
00138             show_error_dialog(ret_message);
00139         } else {
00140             gchar* error_msg = NULL;
00141             switch (errcode)
00142             {
00143             case 1: // application cannot be started
00144             default:
00145                 error_msg = g_strdup_printf(
00146                     _("The '%s' application cannot be opened.\n"
00147                     "Possibly the application is already open. Close it first and try again."),
00148                     filename_display );
00149                 show_error_dialog(error_msg);
00150                 break;
00151             case 4: // application failed to open file (may be handled above with custom message)
00152                 error_msg = g_strdup_printf(_("'%s' cannot be opened."), filename_display);
00153                 show_error_dialog(error_msg);
00154                 break;
00155             case 2: // timeout waiting for application window
00156             case 3: // application has exited before creating a window
00157                 break;
00158             }
00159             g_free(error_msg);
00160         }
00161         return ER_FAIL;
00162     }
00163     return ER_OK;
00164 }
00165 
00166 
00167 static int activate_shortcut (const filelist_entry_t *fileinfo)
00168 {
00169     shortcut_t *shortcut = NULL;
00170     int ret = parse_shortcut_file(fileinfo->directory_path->str,
00171                                   fileinfo->filename->str, &shortcut);
00172     if (ret == ER_NOT_FOUND) {
00173         gchar* error_msg = g_strdup_printf(
00174             _("%s appears to no longer exist.\n"
00175               "Try connecting and ejecting the device from the computer."),
00176               fileinfo->filename_display->str);
00177         show_error_dialog(error_msg);
00178         g_free(error_msg);
00179         return ret;
00180     }
00181     if (ret != ER_OK) return ret;
00182 
00183     switch (shortcut->type)
00184     {
00185         case SHORTCUT_TO_FILE:
00186         {
00187             filelist_entry_t *fileinfo_target = filelist_entry_new();
00188             fileinfo_target->filename         = g_string_new(shortcut->details.file.filename);
00189             fileinfo_target->filename_display = g_string_new( shortcut->name );
00190             fileinfo_target->directory_path   = g_string_new(shortcut->details.file.directory);
00191             fileinfo_target->filetype         = g_string_new( g_extension_pointer(shortcut->details.file.filename));
00192             fileinfo_target->is_directory     = FALSE;
00193             ret = activate_item(fileinfo_target);
00194             filelist_entry_free(fileinfo_target);
00195             break;
00196         }
00197         case SHORTCUT_TO_FOLDER:
00198         {
00199             if (shortcut->details.folder.directory == NULL) {
00200                 ret = ER_NOT_FOUND;
00201                 break;
00202             }
00203             fileview_stop_update_display();
00204             char fullname[512];
00205             sprintf(fullname, "%s/%s", shortcut->details.folder.directory,
00206                                        shortcut->details.folder.filename);
00207             fileview_dir_down(fullname, fileinfo->filename->str);
00208             ret = ER_OK;
00209             break;
00210         }
00211         case SHORTCUT_TO_APPLICATION:
00212             ret = activate_shortcut_to_application(fileinfo, shortcut->details.application.command_line);
00213             break;
00214         
00215         case SHORTCUT_TO_WEB_LOCATION:
00216             ret = activate_shortcut_to_web_location(fileinfo, shortcut->details.web.url);
00217             break;
00218         default:
00219             // not implemented
00220             ret = ER_FAIL;
00221     }
00222 
00223     shortcut_free(shortcut);
00224     return ret;
00225 }
00226 
00227 
00228 // activate: launch viewer, goto directory, ...
00229 int activate_item (const filelist_entry_t *item)
00230 {
00231     g_assert(item);
00232     g_assert(item->directory_path   && item->directory_path->str);
00233     g_assert(item->filename         && item->filename->str        );
00234 
00235     const gchar *filetype = item->filetype->str;
00236     if (strcmp(filetype, SPECIAL_ITEM_NAME) == 0) {
00237         handle_special_item(item);
00238         return ER_OK;
00239     }
00240 
00241     const gchar *filename  = item->filename->str;
00242     const gchar *directory = item->directory_path->str;
00243     if (item->is_directory)
00244     {
00245         fileview_stop_update_display();
00246         char fullname[512];
00247         sprintf(fullname, "%s/%s", directory, filename);
00248         fileview_dir_down(fullname, filename);
00249         return ER_OK;
00250     }
00251 
00252     if (is_shortcut_file_extension(filetype))
00253     {
00254         return activate_shortcut(item);
00255     }
00256 
00257     // normal file, start viewer
00258     const gchar *viewer_cmd = get_viewer_from_file_extension(filetype);
00259     if (viewer_cmd == NULL)
00260     {
00261         gchar *error_msg = g_strdup_printf( _("'%s' cannot be opened; the format is unknown."),
00262                                      filename);
00263         show_error_dialog(error_msg);
00264         g_free(error_msg);
00265         return ER_FAIL;
00266     }
00267 
00268     gchar *cmd_line = g_strdup_printf("%s \"%s/%s\"", viewer_cmd, directory, filename);
00269     gchar *ret_message = NULL;
00270     gint errcode = ipc_sys_start_task(cmd_line, directory,
00271                                       item->filename_display->str, NULL, &ret_message);
00272     if (errcode > 0 && ret_message && ret_message[0] != '\0')
00273     {
00274         ERRORPRINTF("cannot launch viewer, cmd_line [%s], errcode %d [%s]", cmd_line, errcode, ret_message);
00275         show_error_dialog(ret_message);
00276     }
00277 #if MACHINE_IS_DR800S || MACHINE_IS_DR800SG || MACHINE_IS_DR800SW
00278     else if (errcode == 0) filemodel_update_last_read(item);
00279 #endif
00280 
00281     g_free(ret_message);
00282     g_free(cmd_line);
00283     return ER_OK;
00284 }
00285 
00286 
00287 static void delete_item_from_db(erMetadb db, const filelist_entry_t *item)
00288 {
00289     g_assert(db);
00290     if (item->is_directory) {
00291         ermetadb_global_remove_folder(db, item->directory_path->str, item->filename->str);
00292     } else {
00293         ermetadb_global_remove_file(db, item->directory_path->str, item->filename->str);
00294     }
00295 }
00296 
00297 
00298 int delete_item(const filelist_entry_t  *item)
00299 {
00300     g_assert(item);
00301     g_assert(item->filename          && item->filename->str        );
00302     g_assert(item->filetype          && item->filetype->str        );
00303     g_assert(item->directory_path    && item->directory_path->str  );
00304 
00305     const gchar *filename = item->filename->str;
00306     const gchar *filetype = item->filetype->str;
00307 
00308     LOGPRINTF( "entry: filename [%s] dirpath [%s]", filename, item->directory_path->str);
00309 
00310     // tell sysd to close document, then wait for a reply from sysd
00311     gchar *filepath = g_strdup_printf("%s/%s", item->directory_path->str, filename);
00312 
00313     const gchar *viewer_cmd = get_viewer_from_file_extension(filetype);
00314     if (viewer_cmd)
00315     {
00316         gchar *cmd_line = g_strdup_printf("%s \"%s\"", viewer_cmd, filepath);
00317         ipc_sys_stop_task(cmd_line);
00318         g_free(cmd_line);
00319     }
00320 
00321     // remove file or directory from FS
00322     const char *argv[10];
00323     unsigned int argc = 0;
00324     argv[argc++] = "rm";
00325     argv[argc++] = "-fr";
00326     argv[argc++] = filepath;
00327     argv[argc++] = NULL;
00328     g_assert(argc < sizeof(argv)/sizeof(argv[0]));
00329     gint stat;
00330     GError *err = NULL;
00331     gboolean ok = g_spawn_sync( NULL,          // working directory: inherit
00332                        (char**)argv,           // child's argument vector
00333                        NULL,                   // environment: inherit
00334                        G_SPAWN_SEARCH_PATH,    // flags
00335                        NULL,                   // child_setup: none
00336                        NULL,                   // child setup data: none
00337                        NULL,                   // stdout: not interested
00338                        NULL,                   // stderr: not interested
00339                        &stat,                  // exit status
00340                        &err                );  // error return
00341     g_free(filepath);
00342     if (!ok)
00343     {
00344         ERRORPRINTF("g_spawn_sync error [%s] on delete [%s/%s]",
00345                 err->message, item->directory_path->str, filename);
00346         g_clear_error(&err);
00347         return ER_FAIL;
00348     }
00349 
00350     delete_item_from_db(filemodel_get_database(), item);
00351     return ER_OK;
00352 }
00353 
00354 
00355 static gboolean shortcut_allowed(const filelist_entry_t *fileinfo)
00356 {
00357     // Special entries
00358     if (strcmp(fileinfo->filetype->str, SPECIAL_ITEM_NAME) == 0) return FALSE;
00359 
00360     // Shortcuts
00361     if (is_shortcut_file_extension(fileinfo->filetype->str)) return FALSE;
00362 
00363     // New Note entry
00364     if (strcmp(fileinfo->filename->str, "new") == 0) return FALSE;
00365 
00366     return TRUE;
00367 }
00368 
00369 
00370 int create_shortcut_item (const filelist_entry_t *item)
00371 {
00372     g_assert(item);
00373     g_assert(item->filename          && item->filename->str        );
00374     g_assert(item->filename_display  && item->filename_display->str);
00375     g_assert(item->filetype          && item->filetype->str        );
00376     g_assert(item->directory_path    && item->directory_path->str  );
00377 
00378     if (!shortcut_allowed(item)) {
00379         gchar *error_msg = g_strdup_printf(_("A shortcut cannot be created for this item"));
00380         show_error_dialog(error_msg);
00381         g_free(error_msg);
00382         return ER_FORBIDDEN;
00383     }
00384 
00385     const gchar *mountpoint = ipc_get_media();
00386     char shortcut_dir[256];
00387     sprintf(shortcut_dir, "%s/%s", mountpoint, DIR_SHORTCUTS);
00388 
00389     // create shortcut dir if it doesn't exist
00390     g_mkdir_with_parents (shortcut_dir, 644);
00391 
00392     // create shortcut file on disk
00393     const gchar *target_dir = item->directory_path->str;
00394     const gchar *target_file = item->filename->str;
00395     const gchar *target_display = item->filename_display->str;
00396     GString *shortcut_file = g_string_new("");
00397     int ret = create_shortcut_file(target_dir, target_file, target_display, shortcut_dir, shortcut_file);
00398     if (ret != ER_OK) {
00399         ERRORPRINTF("cannot create shortcut for %s/%s", target_dir, target_file);
00400         g_string_free(shortcut_file, TRUE);
00401         return ret;
00402     }
00403 
00404     // add to metadb
00405     erMetadb db = filemodel_get_database();
00406     gint64 now = time(NULL);
00407     char subtitle[512];
00408     // NOTE: assumes shortcut is created on mountpoint, skip
00409     snprintf(subtitle, 512, "%s/%s", target_dir + strlen(mountpoint), target_file);
00410     subtitle[sizeof(subtitle)-1] = 0;
00411     char* cp = subtitle;
00412     if (subtitle[0] == '/') cp++;
00413     ret = ermetadb_global_add_file(db, shortcut_dir, shortcut_file->str, 0, now, target_display, cp, "");
00414     if (ret != ER_OK) {
00415         ERRORPRINTF("cannot add %s/%s to metadb", shortcut_dir, shortcut_file->str);
00416     }
00417 
00418     g_string_free(shortcut_file, TRUE);
00419     return ret;
00420 }
00421 
Generated by  doxygen 1.6.2-20100208