/******************************* LICENCE ************************************** * Any code in this file may be redistributed or modified under the terms of * the GNU General Public Licence as published by the Free Software * Foundation; version 2 of the licence. ****************************** END LICENCE ***********************************/ /****************************************************************************** * Author: * Andrew Smith, http://littlesvr.ca/misc/contactandrew.php * * Contributors: * ******************************************************************************/ #include #include #include #include #include "isomaster.h" #define MAX_RANDOM_BASE_NAME_LEN 26 #define RANDOM_STR_NAME_LEN 6 /* files that I created in the temp dir for editing */ TempFileCreated* GBLtempFilesList = NULL; extern bool GBLisoPaneActive; extern GtkWidget* GBLisoTreeView; extern char* GBLisoCurrentDir; extern VolInfo GBLvolInfo; extern GtkWidget* GBLmainWindow; extern bool GBLisoChangesProbable; extern GtkWidget* GBLeditorFld; extern GtkWidget* GBLviewerFld; extern GtkWidget* GBLtempDirFld; /****************************************************************************** * addToTempFilesList() * Appends a node to the front of the list. * */ void addToTempFilesList(const char* pathAndName) { TempFileCreated* newNode; newNode = malloc(sizeof(TempFileCreated)); if(newNode == NULL) fatalError("newNode = malloc(sizeof(TempFileCreated)) failed\n"); newNode->pathAndName = malloc(strlen(pathAndName) + 1); if(newNode == NULL) fatalError("newNode.pathAndName = malloc(strlen(pathAndName) + 1) failed\n"); strcpy(newNode->pathAndName, pathAndName); newNode->next = GBLtempFilesList; GBLtempFilesList = newNode; } void deleteTempFiles(void) { TempFileCreated* next; while(GBLtempFilesList != NULL) { next = GBLtempFilesList->next; unlink(GBLtempFilesList->pathAndName); free(GBLtempFilesList->pathAndName); free(GBLtempFilesList); GBLtempFilesList = next; } } void editSelectedBtnCbk(GtkMenuItem *menuitem, gpointer data) { GtkTreeSelection* selection; /* do nothing if no image open */ if(!GBLisoPaneActive) return; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(GBLisoTreeView)); /* there's just one row selected but this is the easiest way to do it */ gtk_tree_selection_selected_foreach(selection, editSelectedRowCbk, NULL); /* can't put this in the callback because gtk complains */ refreshIsoView(); } void editSelectedRowCbk(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iterator, gpointer data) { int fileType; char* itemName; char* randomizedItemName; char* pathAndNameOnFs; /* to extract to and add from */ char* pathAndNameOnIso; /* to delete from iso */ int rc; GtkWidget* warningDialog; gtk_tree_model_get(model, iterator, COLUMN_HIDDEN_TYPE, &fileType, COLUMN_FILENAME, &itemName, -1); if(fileType != FILE_TYPE_REGULAR) { warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("'%s' is not a regular file"), itemName); gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE); gtk_dialog_run(GTK_DIALOG(warningDialog)); gtk_widget_destroy(warningDialog); g_free(itemName); return; } /* create full path and name for the file on the iso */ pathAndNameOnIso = malloc(strlen(GBLisoCurrentDir) + strlen(itemName) + 1); if(pathAndNameOnIso == NULL) fatalError("malloc(strlen(GBLisoCurrentDir) + strlen(itemName) + 1) failed"); strcpy(pathAndNameOnIso, GBLisoCurrentDir); strcat(pathAndNameOnIso, itemName); /* create full path and name for the extracted file */ randomizedItemName = makeRandomFilename(itemName); pathAndNameOnFs = malloc(strlen(gtk_entry_get_text(GTK_ENTRY(GBLtempDirFld))) + strlen(randomizedItemName) + 2); if(pathAndNameOnFs == NULL) fatalError("malloc(strlen(gtk_entry_get_text(GTK_ENTRY(GBLtempDirFld))) + " "strlen(randomizedItemName) + 2) failed"); strcpy(pathAndNameOnFs, gtk_entry_get_text(GTK_ENTRY(GBLtempDirFld))); strcat(pathAndNameOnFs, "/"); /* doesn't hurt even if not needed */ strcat(pathAndNameOnFs, randomizedItemName); /* disable warnings, so user isn't confused with 'continue' buttons */ bool(*savedWarningCbk)(const char*) = GBLvolInfo.warningCbk; GBLvolInfo.warningCbk = NULL; /* extract the file to the temporary directory */ rc = bk_extract_as(&GBLvolInfo, pathAndNameOnIso, gtk_entry_get_text(GTK_ENTRY(GBLtempDirFld)), randomizedItemName, false, activityProgressUpdaterCbk); if(rc <= 0) { warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Failed to extract '%s': '%s'"), pathAndNameOnIso, bk_get_error_string(rc)); gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE); gtk_dialog_run(GTK_DIALOG(warningDialog)); gtk_widget_destroy(warningDialog); g_free(itemName); free(randomizedItemName); free(pathAndNameOnFs); free(pathAndNameOnIso); GBLvolInfo.warningCbk = savedWarningCbk; return; } addToTempFilesList(pathAndNameOnFs); /* start the editor */ if(!fork()) { execlp(gtk_entry_get_text(GTK_ENTRY(GBLeditorFld)), "editor", pathAndNameOnFs, NULL); printf("Failed to execute %s, error %d\n", gtk_entry_get_text(GTK_ENTRY(GBLeditorFld)), errno); printf("!! need to send a signal to iso master here to show a dialog\n"); exit(1); } /* delete the file from the iso */ rc = bk_delete(&GBLvolInfo, pathAndNameOnIso); if(rc <= 0) { warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Failed to delete '%s': '%s'"), pathAndNameOnIso, bk_get_error_string(rc)); gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE); gtk_dialog_run(GTK_DIALOG(warningDialog)); gtk_widget_destroy(warningDialog); g_free(itemName); free(randomizedItemName); free(pathAndNameOnFs); free(pathAndNameOnIso); GBLvolInfo.warningCbk = savedWarningCbk; return; } GBLisoChangesProbable = true; /* add the file back fom tmp */ rc = bk_add_as(&GBLvolInfo, pathAndNameOnFs, GBLisoCurrentDir, itemName, activityProgressUpdaterCbk); if(rc <= 0) { warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Failed to add '%s': '%s'"), pathAndNameOnFs, bk_get_error_string(rc)); gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE); gtk_dialog_run(GTK_DIALOG(warningDialog)); gtk_widget_destroy(warningDialog); } g_free(itemName); free(randomizedItemName); free(pathAndNameOnFs); free(pathAndNameOnIso); GBLvolInfo.warningCbk = savedWarningCbk; } /* caller must free the string returned */ char* makeRandomFilename(const char* sourceName) { int sourceNameLen; char* newName; char randomStr[RANDOM_STR_NAME_LEN]; int numRandomCharsFilled; if(strlen(sourceName) > MAX_RANDOM_BASE_NAME_LEN) sourceNameLen = MAX_RANDOM_BASE_NAME_LEN; else sourceNameLen = strlen(sourceName); newName = malloc(sourceNameLen + RANDOM_STR_NAME_LEN + 2); if(newName == NULL) fatalError("newName = malloc(sourceNameLen + RANDOM_STR_NAME_LEN + 2) failed\n"); numRandomCharsFilled = 0; while(numRandomCharsFilled < RANDOM_STR_NAME_LEN) { char oneRandomChar; bool gotGoodChar; gotGoodChar = false; while(!gotGoodChar) { oneRandomChar = random(); if(64 < oneRandomChar && oneRandomChar < 91) { gotGoodChar = true; } } randomStr[numRandomCharsFilled] = oneRandomChar; numRandomCharsFilled++; } strncpy(newName, randomStr, RANDOM_STR_NAME_LEN); newName[RANDOM_STR_NAME_LEN] = '\0'; strcat(newName, "-"); strncat(newName, sourceName, sourceNameLen); newName[RANDOM_STR_NAME_LEN + sourceNameLen + 1] = '\0'; return newName; } void viewSelectedBtnCbk(GtkMenuItem *menuitem, gpointer data) { GtkTreeSelection* selection; /* do nothing if no image open */ if(!GBLisoPaneActive) return; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(GBLisoTreeView)); /* there's just one row selected but this is the easiest way to do it */ gtk_tree_selection_selected_foreach(selection, viewSelectedRowCbk, NULL); } void viewSelectedRowCbk(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iterator, gpointer data) { int fileType; char* itemName; char* randomizedItemName; char* pathAndNameOnFs; /* to extract to and add from */ char* pathAndNameOnIso; /* to delete from iso */ int rc; GtkWidget* warningDialog; gtk_tree_model_get(model, iterator, COLUMN_HIDDEN_TYPE, &fileType, -1); gtk_tree_model_get(model, iterator, COLUMN_HIDDEN_TYPE, &fileType, COLUMN_FILENAME, &itemName, -1); if(fileType != FILE_TYPE_REGULAR) { warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("'%s' is not a regular file"), itemName); gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE); gtk_dialog_run(GTK_DIALOG(warningDialog)); gtk_widget_destroy(warningDialog); g_free(itemName); return; } /* create full path and name for the file on the iso */ pathAndNameOnIso = malloc(strlen(GBLisoCurrentDir) + strlen(itemName) + 1); if(pathAndNameOnIso == NULL) fatalError("malloc(strlen(GBLisoCurrentDir) + strlen(itemName) + 1) failed"); strcpy(pathAndNameOnIso, GBLisoCurrentDir); strcat(pathAndNameOnIso, itemName); /* create full path and name for the extracted file */ randomizedItemName = makeRandomFilename(itemName); pathAndNameOnFs = malloc(strlen(gtk_entry_get_text(GTK_ENTRY(GBLtempDirFld))) + strlen(randomizedItemName) + 2); if(pathAndNameOnFs == NULL) fatalError("malloc(strlen(gtk_entry_get_text(GTK_ENTRY(GBLtempDirFld))) + " "strlen(randomizedItemName) + 2) failed"); strcpy(pathAndNameOnFs, gtk_entry_get_text(GTK_ENTRY(GBLtempDirFld))); strcat(pathAndNameOnFs, "/"); /* doesn't hurt even if not needed */ strcat(pathAndNameOnFs, randomizedItemName); /* disable warnings, so user isn't confused with 'continue' buttons */ bool(*savedWarningCbk)(const char*) = GBLvolInfo.warningCbk; GBLvolInfo.warningCbk = NULL; /* extract the file to the temporary directory */ rc = bk_extract_as(&GBLvolInfo, pathAndNameOnIso, gtk_entry_get_text(GTK_ENTRY(GBLtempDirFld)), randomizedItemName, false, activityProgressUpdaterCbk); if(rc <= 0) { warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Failed to extract '%s': '%s'"), pathAndNameOnIso, bk_get_error_string(rc)); gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE); gtk_dialog_run(GTK_DIALOG(warningDialog)); gtk_widget_destroy(warningDialog); g_free(itemName); free(randomizedItemName); free(pathAndNameOnFs); free(pathAndNameOnIso); GBLvolInfo.warningCbk = savedWarningCbk; return; } addToTempFilesList(pathAndNameOnFs); /* start the viewer */ if(!fork()) { execlp(gtk_entry_get_text(GTK_ENTRY(GBLviewerFld)), "viewer", pathAndNameOnFs, NULL); printf("Failed to execute %s, error %d\n", gtk_entry_get_text(GTK_ENTRY(GBLviewerFld)), errno); printf("!! need to send a signal to iso master here to show a dialog\n"); exit(1); } g_free(itemName); free(randomizedItemName); free(pathAndNameOnFs); free(pathAndNameOnIso); GBLvolInfo.warningCbk = savedWarningCbk; }