ghex_heraia_interface.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /*
00003   ghex_heraia_interface.c
00004   heraia - an hexadecimal file editor and analyser based on ghex
00005 
00006   (C) Copyright 2005 - 2010 Olivier Delhomme
00007   e-mail : heraia@delhomme.org
00008   URL    : http://heraia.tuxfamily.org
00009 
00010   This program is free software; you can redistribute it and/or modify
00011   it under the terms of the GNU General Public License as published by
00012   the Free Software Foundation; either version 2, or  (at your option)
00013   any later version.
00014 
00015   This program is distributed in the hope that it will be useful,
00016   but WITHOUT ANY WARRANTY;  without even the implied warranty of
00017   MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE.  See the
00018   GNU General Public License for more details.
00019 
00020   You should have received a copy of the GNU General Public License
00021   along with this program; if not, write to the Free Software
00022   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
00023 /**
00024  * @file ghex_heraia_interface.c
00025  * An interface to the ghex library -> this adds an abstract layer.
00026  */
00027 #include <libheraia.h>
00028 
00029 
00030 /**
00031  * @fn HERAIA_ERROR heraia_hex_document_new(heraia_struct_t *main_struct, char *filename)
00032  *  Removes the old document if it exists and adds a new one
00033  *  from the filename 'filename'
00034  * @param main_struct : main structure
00035  * @param filename : a char * representing an existing file named "filename"
00036  * @return Always returns HERAIA_NOERR;
00037  * @todo : do something to take errors into account
00038  */
00039 doc_t *heraia_hex_document_new(heraia_struct_t *main_struct, char *filename)
00040 {
00041     Heraia_Document *hex_doc = NULL;
00042     GtkWidget *hex_widget = NULL;
00043     doc_t *doc = NULL;
00044 
00045     /* Creating a new hex document */
00046     hex_doc = hex_document_new_from_file(filename);
00047 
00048     if (hex_doc != NULL)
00049         {
00050             /* creating a new view to this new document */
00051             hex_widget = hex_document_add_view(hex_doc);
00052 
00053             /* displaying the offsets if requested */
00054             gtk_hex_show_offsets(GTK_HEX(hex_widget), is_toggle_button_activated(main_struct->xmls->main, "mp_display_offset_bt"));
00055 
00056             /* joining those two new structures in one */
00057             doc = new_doc_t(hex_doc, hex_widget);
00058 
00059             /* Adding this new doc to the list of docs (here a GPtrArray) */
00060             g_ptr_array_add(main_struct->documents, doc);
00061 
00062             /* signal connection on cursor moves */
00063             connect_cursor_moved_signal(main_struct, hex_widget);
00064 
00065             return doc;
00066          }
00067      else
00068          {
00069              return NULL;
00070          }
00071 }
00072 
00073 
00074 /**
00075  * Retrieves the filename of a document which ever it is !
00076  * @param doc : an Heraia_Document
00077  * @return returns the filename of that document.
00078  */
00079 gchar *heraia_hex_document_get_filename(Heraia_Document *hex_doc)
00080 {
00081     if (hex_doc != NULL)
00082         {
00083             return hex_doc->file_name;
00084         }
00085     else
00086         {
00087             return NULL;
00088         }
00089 }
00090 
00091 
00092 /**
00093  * Retrieves from a doc_t * document it's filename, which ever it is
00094  * @param doc : an existing doc_t
00095  * @return returns the filename of that document.
00096  */
00097 gchar *doc_t_document_get_filename(doc_t *doc)
00098 {
00099     if (doc != NULL)
00100         {
00101             return heraia_hex_document_get_filename(doc->hex_doc);
00102         }
00103     else
00104         {
00105             return NULL;
00106         }
00107 }
00108 
00109 
00110 /**
00111  * @fn HERAIA_ERROR heraia_hex_document_save(heraia_struct_t *main_struct)
00112  * Saves an open and edited document
00113  * @param current_doc : current edited document (doc_t * structure)
00114  * @return returns HERAIA_NOERR if everything went ok or HERAIA_FILE_ERROR in case of an error
00115  */
00116 HERAIA_ERROR heraia_hex_document_save(doc_t *current_doc)
00117 {
00118     gint return_value = FALSE;
00119 
00120     if (current_doc != NULL)
00121         {
00122             if (current_doc->hex_doc != NULL)
00123                 {
00124                     return_value = hex_document_write(current_doc->hex_doc);
00125                 }
00126         }
00127 
00128     if (return_value != FALSE)
00129         {
00130             return HERAIA_NOERR;
00131         }
00132     else
00133         {
00134             return HERAIA_FILE_ERROR;
00135         }
00136 }
00137 
00138 
00139 /**
00140  * Saves an opened and edited document to a new file
00141  * @param current_doc : current edited document (doc_t * structure)
00142  * @param filename : the new filename where to save the file
00143  * @return returns HERAIA_NOERR if everything went ok or HERAIA_FILE_ERROR in case of an error
00144  */
00145 HERAIA_ERROR heraia_hex_document_save_as(doc_t *current_doc, gchar *filename)
00146 {
00147     gint return_value = FALSE;
00148     FILE *fp = NULL;
00149     gint i = 0;
00150     gchar *path_end = NULL; /**< to make libghex happy ! */
00151 
00152     if (current_doc != NULL && current_doc->hex_doc != NULL && filename != NULL)
00153        {
00154             fp = fopen(filename, "w");
00155             if (fp != NULL)
00156                 {
00157                     return_value = hex_document_write_to_file(current_doc->hex_doc, fp);
00158                     fclose(fp);
00159 
00160                     /* path_end stuff from ghex-window.c from ghex project !!! */
00161                     for(i = strlen(current_doc->hex_doc->file_name);
00162                             (i >= 0) && (current_doc->hex_doc->file_name[i] != '/');
00163                             i--);
00164                     if (current_doc->hex_doc->file_name[i] == '/')
00165                         {
00166                             path_end = &current_doc->hex_doc->file_name[i+1];
00167                         }
00168                     else
00169                         {
00170                             path_end = current_doc->hex_doc->file_name;
00171                         }
00172 
00173                     current_doc->hex_doc->path_end = g_filename_to_utf8(path_end, -1, NULL, NULL, NULL);
00174                 }
00175         }
00176 
00177     if (return_value != FALSE)
00178         {
00179             return HERAIA_NOERR;
00180         }
00181     else
00182         {
00183             return HERAIA_FILE_ERROR;
00184         }
00185 }
00186 
00187 
00188 /**
00189  *  Deals with the endianness of 'len' bytes located in 'result'
00190  *  for BIG_ENDIAN we only swap bytes if we have two or more of them
00191  *  if we have only one byte, we reverse its order
00192  *  if endianness is MIDDLE_ENDIAN we swap only four or more bytes
00193  *  Here we might have funny things with len corresponding to 24 or 56 bits
00194  *  for example
00195  *  @warning Assumption is made that the default order is LITTLE_ENDIAN (which may
00196  *           not be true on some systems !)
00197  *  @warning We do assume that 'result' really contains 'len' bytes of data previously
00198  *           gmalloc'ed
00199  *  @param len : len bytes to change endianness
00200  *  @param endianness : H_DI_BIG_ENDIAN or H_DI_MIDDLE_ENDIAN we consider that there
00201  *         is nothing to do with H_DI_LITTLE_ENDIAN
00202  *  @param[in,out] result : contains the bytes to be swaped and at the end, contains
00203  *                 the result.
00204  */
00205 static void change_endianness(guint len, guint endianness, guchar *result)
00206 {
00207     if (endianness == H_DI_BIG_ENDIAN)
00208         {
00209             if (len > 1) /* We swap bytes only if we have two or more */
00210                 {
00211                     swap_bytes(result, 0, len-1);
00212                 }
00213             else
00214                 {
00215                     reverse_byte_order(result);  /* Only one byte and big endian requested */
00216                 }
00217         }
00218     else if (endianness == H_DI_MIDDLE_ENDIAN && len >= 4)
00219         {
00220             swap_bytes(result, 0, (len/2)-1);
00221             swap_bytes(result, (len/2), len-1);
00222         }
00223 }
00224 
00225 
00226 /**
00227  *  Returns 'len' number of bytes located at 'pos' in the Heraia_Hex
00228  *  document and puts it in the result variable
00229  *
00230  *  @warning We assume that a previous g_malloc has been done in order to
00231  *           use the function. Here we need the "swap_bytes" function
00232  *           defined in the decode.h header in order to take the endianness
00233  *           into account
00234  *  @param gh : A Heraia_Hex document.
00235  *  @param pos : position where we want to begin to copy bytes
00236  *  @param len : number of bytes we want to copy
00237  *  @param endianness : endianness we want to apply to the bytes we want to copy
00238  *  @param[out] result : a previously g_malloc'ed gchar * string that will contain
00239  *              copied bytes.
00240  *  @return TRUE if everything went ok, FALSE otherwise
00241  */
00242 gboolean ghex_memcpy(Heraia_Hex *gh, guint64 pos, guint len, guint endianness, guchar *result)
00243 {
00244     guint i;
00245 
00246     if (result == NULL || gh == NULL)
00247         {
00248             return FALSE;
00249         }
00250     else if ((pos < 0) || ((pos+len-1) > ghex_file_size(gh))) /* pos located in the file limits ! */
00251         {
00252             return FALSE;
00253         }
00254     else
00255         {
00256             /* Extracts len bytes from the Ghex widget */
00257             for (i=0; i<len ; i++)
00258                 {
00259                         result[i] = gtk_hex_get_byte(gh, pos+i);
00260                 }
00261 
00262             /* Deals with endianness to rearrange datas */
00263             change_endianness(len, endianness, result);
00264 
00265             return TRUE;
00266         }
00267 }
00268 
00269 
00270 /**
00271  *  Gets the data from the hexwidget under the cursor, a wrapper to the
00272  *  ghex_memcpy function.
00273  *  @warning guchar *c MUST have been pre allocated BEFORE the call.
00274  *
00275  * @param hex_widget : MUST be a Heraia_Hex widget
00276  * @param length : can be anything but MUST be strictly less than the size allocated
00277  *        to *c
00278  * @param endianness : H_DI_BIG_ENDIAN, H_DI_MIDDLE_ENDIAN or H_DI_LITTLE_ENDIAN
00279  * @param c : a previously g_malloc'ed gchar * string that will contain
00280  *            copied bytes.
00281  */
00282 gboolean ghex_get_data(GtkWidget *hex_widget, guint length, guint endianness, guchar *c)
00283 {
00284     Heraia_Hex *gh = GTK_HEX(hex_widget);
00285 
00286     if (gh != NULL)
00287         {
00288             return ghex_get_data_position(hex_widget, gtk_hex_get_cursor(gh), length, endianness, c);
00289         }
00290     else
00291         {
00292             return FALSE;
00293         }
00294 }
00295 
00296 
00297 /**
00298  *  Wrapper to the hex_document_set_data function
00299  * @param doc : the document searched
00300  * @param position : the position where to set the data
00301  * @param rep_len : the len of the data to be replaced in the document doc
00302  * @param len : the len of the data
00303  * @param data : the data that will replace the one in the document
00304  */
00305 void ghex_set_data(doc_t *doc, guint64 position, guint rep_len, guint len, guchar *data)
00306 {
00307     if (doc != NULL && doc->hex_doc != NULL && data != NULL)
00308         {
00309             hex_document_set_data(doc->hex_doc, position, len, rep_len, data, TRUE);
00310         }
00311 }
00312 
00313 
00314 /**
00315  *  Gets the data from the hexwidget, a wrapper to the ghex_memcpy
00316  *  function.
00317  *  @warning guchar *c MUST have been pre allocated BEFORE the call.
00318  *
00319  * @param hex_widget : MUST be a Heraia_Hex widget
00320  * @param pos : position in the file where we want to get the data
00321  * @param length : can be anything but MUST be strictly less than the size allocated
00322  *        to *c
00323  * @param endianness : H_DI_BIG_ENDIAN, H_DI_MIDDLE_ENDIAN or H_DI_LITTLE_ENDIAN
00324  * @param c : a previously g_malloc'ed gchar * string that will contain
00325  *            copied bytes.
00326  */
00327 gboolean ghex_get_data_position(GtkWidget *hex_widget, guint64 pos, guint length, guint endianness, guchar *c)
00328 {
00329     gboolean result = FALSE;
00330     Heraia_Hex *gh = GTK_HEX(hex_widget);
00331 
00332     if (gh != NULL)
00333         {
00334             result = ghex_memcpy(gh, pos, length, endianness, c);
00335         }
00336     else
00337         {
00338             result = FALSE;
00339         }
00340 
00341     return result;
00342 }
00343 
00344 
00345 /**
00346  * Gets data from a defined position and formats it in an ascii displayable form
00347  * @param hex_widget : MUST be a Heraia_Hex widget
00348  * @param pos : position in the file where we want to get the data
00349  * @param length : length of the data to get
00350  * @param endianness : H_DI_BIG_ENDIAN, H_DI_MIDDLE_ENDIAN or H_DI_LITTLE_ENDIAN
00351  * @return the newly allocated string that contains the ascii translation from
00352  *         the data or NULL if something went wrong.
00353  */
00354 guchar *ghex_get_data_to_ascii(GtkWidget *hex_widget, guint64 pos, guint length, guint endianness)
00355 {
00356     Heraia_Hex *gh = GTK_HEX(hex_widget);
00357     guchar *c = NULL;
00358     guchar *result = NULL;
00359     gint i = 0;
00360 
00361     c = (guchar *) g_malloc0 (sizeof(guchar)*(length + 1));
00362 
00363     if (ghex_memcpy(gh, pos, length, endianness, c) == TRUE)
00364         {
00365 
00366             result = (guchar *) g_malloc0 (sizeof(guchar)*(length + 2));
00367 
00368             for(i = 0; i < length; i++)
00369                 {
00370                     if (is_displayable(c[i]))
00371                         {
00372                             result[i] = c[i];
00373                         }
00374                     else
00375                         {
00376                             result[i] = '.';
00377                         }
00378                 }
00379 
00380             i++;
00381             result[i] = (guchar) 0;
00382 
00383             g_free(c);
00384 
00385             return result;
00386         }
00387     else
00388         {
00389             g_free(c);
00390             return NULL;
00391         }
00392 }
00393 
00394 
00395 /**
00396  * Gets data from a defined position and formats it in an hex displayable form
00397  * @param hex_widget : MUST be a Heraia_Hex widget
00398  * @param pos : position in the file where we want to get the data
00399  * @param length : length of the data to get
00400  * @param endianness : H_DI_BIG_ENDIAN, H_DI_MIDDLE_ENDIAN or H_DI_LITTLE_ENDIAN
00401  * @return the newly allocated string that contains the ascii translation from
00402  *         the data or NULL if something went wrong.
00403  */
00404 guchar *ghex_get_data_to_hex(GtkWidget *hex_widget, guint64 pos, guint length, guint endianness)
00405 {
00406     Heraia_Hex *gh = GTK_HEX(hex_widget);
00407     static guchar hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
00408     guchar *c = NULL;
00409     guchar *result = NULL;
00410     gint i = 0;
00411     gint j = 0;
00412     gint high = 0;
00413     gint low = 0;
00414 
00415     c = (guchar *) g_malloc0 (sizeof(guchar)*(length + 1));
00416 
00417     if (ghex_memcpy(gh, pos, length, endianness, c) == TRUE)
00418         {
00419 
00420             result = (guchar *) g_malloc0 (sizeof(guchar)*( 3 * length + 2));
00421 
00422             j = 0;
00423             for(i = 0; i < length; i++)
00424                 {
00425                     low = c[i] & 0x0F;
00426                     high = (c[i] & 0xF0) >> 4;
00427 
00428                     result[j] = hex[high];
00429                     j++;
00430                     result[j] = hex[low];
00431                     j++;
00432 
00433                     if (i % gh->group_type == 0)
00434                         {
00435                             result[j] = ' ';
00436                             j++;
00437                         }
00438                 }
00439 
00440             j++;
00441             result[j] = (guchar) 0;
00442 
00443             g_free(c);
00444 
00445             return result;
00446         }
00447     else
00448         {
00449             g_free(c);
00450             return NULL;
00451         }
00452 }
00453 
00454 /**
00455  *  Returns the file size of an opened Heraia_Hex document.
00456  * @param gh : the widget of a an opened Heraia_Hex document
00457  * @return returns the file size of that document
00458  */
00459 guint64 ghex_file_size(Heraia_Hex *gh)
00460 {
00461     if (gh != NULL && gh->document != NULL)
00462         {
00463             return gh->document->file_size;
00464         }
00465     else
00466         {
00467             return 0;
00468         }
00469 }
00470 
00471 
00472 /**
00473  *  Retrieves the cursor's position from the current hexwidget
00474  * @param hex_widget : the widget that displays the hex document
00475  * @return returns the cursor's position
00476  */
00477 guint64 ghex_get_cursor_position(GtkWidget *hex_widget)
00478 {
00479     Heraia_Hex *gh = GTK_HEX(hex_widget);
00480 
00481     if (gh != NULL)
00482         {
00483               return gtk_hex_get_cursor(gh);
00484         }
00485     else
00486         {
00487               return 0;
00488         }
00489 }
00490 
00491 
00492 /**
00493  * Sets the cursor at the defined position in the hexwidget
00494  * @param hex_widget : the widget that displays the hex document
00495  * @param position : the position where we want to go
00496  * @warning no checks are made here (limits and such ...). Checks are made in
00497  *          the gtk_hex_set_cursor function itself.
00498  */
00499 void ghex_set_cursor_position(GtkWidget *hex_widget, guint64 position)
00500 {
00501 
00502     Heraia_Hex *gh = GTK_HEX(hex_widget);
00503 
00504     if (gh != NULL)
00505         {
00506               gtk_hex_set_cursor(gh, position);
00507         }
00508 }
00509 
00510 /** @todo a uniq function that will unify ghex_find_forward and ghex_find_backward */
00511 /**
00512  * Wrapper to the hex_document_find_forward function
00513  * Tries to find search_buffer in doc
00514  * @param doc : the document searched
00515  * @param search_buffer : the string searched for
00516  * @param buffer_size : size of the buffer
00517  * @param[out] position (if any) of the found string
00518  * @return True if something has been found. False otherwise
00519  */
00520 gboolean ghex_find_forward(doc_t *doc, guchar *search_buffer, guint buffer_size, guint64 *position)
00521 {
00522     guint64 current_position = 0;
00523     guint offset = 0;
00524     gboolean result = FALSE;
00525 
00526     if (doc != NULL && doc->hex_widget != NULL && doc->hex_doc != NULL)
00527         {
00528             current_position = *position;
00529             result = hex_document_find_forward(doc->hex_doc, current_position + 1, search_buffer, buffer_size, &offset);
00530 
00531             if (result == TRUE)
00532                 {
00533                     *position = (guint64) offset;
00534                     return TRUE;
00535                 }
00536             else
00537                 {
00538                     *position = 0;
00539                     return FALSE;
00540                 }
00541         }
00542     else
00543         {
00544             *position = 0;
00545             return FALSE;
00546         }
00547 }
00548 
00549 
00550 /**
00551  * Wrapper to the hex_document_compare_data function
00552  * Compares data from string to the one contained in doc at position position
00553  * and with len buffer_size
00554  * @param doc : the document where we want to compare data
00555  * @param string : the string we want to compare
00556  * @param buffer_size : size of the buffer string
00557  * @param position the localisation in the document where we want to compare
00558  *        thing
00559  * @return a gint 0 means that at the given position and for the len buffer_size
00560  *         the document doc contains exactly the string.
00561  *         -1 if an error occured.
00562  */
00563 gint ghex_compare_data(doc_t *doc, guchar *string,  guint buffer_size, guint64 position)
00564 {
00565 
00566     if (doc != NULL && doc->hex_doc != NULL && string != NULL)
00567         {
00568             return hex_document_compare_data(doc->hex_doc, string, (gint) position, buffer_size);
00569         }
00570     else
00571         {
00572             return -1;
00573         }
00574 }
00575 
00576 
00577 /**
00578  * Wrapper to the hex_document_find_backward function
00579  * Tries to find search_buffer in doc
00580  * @param doc : the document searched
00581  * @param search_buffer : the string searched for
00582  * @param buffer_size : size of the buffer
00583  * @param[out] : position (if any) of the found string
00584  * @return True if something has been found. False otherwise
00585  */
00586 gboolean ghex_find_backward(doc_t *doc, guchar *search_buffer, guint buffer_size, guint64 *position)
00587 {
00588     guint64 current_position = 0;
00589     guint offset = 0;
00590     gboolean result = FALSE;
00591 
00592     if (doc != NULL && doc->hex_widget != NULL && doc->hex_doc != NULL)
00593         {
00594             current_position = *position;
00595             result = hex_document_find_backward(doc->hex_doc, current_position - 1, search_buffer, buffer_size, &offset);
00596 
00597             if (result == TRUE)
00598                 {
00599                     *position = (guint64) offset;
00600                     return TRUE;
00601                 }
00602             else
00603                 {
00604                     *position = 0;
00605                     return FALSE;
00606                 }
00607         }
00608     else
00609         {
00610             *position = 0;
00611             return FALSE;
00612         }
00613 }
00614 
00615 
00616 /**
00617  * Retrieves the selection made (if any) in the hex widget
00618  * @param hex_widget : the widget that displays the hex document
00619  * @return returns a filed selection_t structure
00620  */
00621 selection_t *ghex_get_selection(GtkWidget *hex_widget)
00622 {
00623     Heraia_Hex *gh = GTK_HEX(hex_widget);
00624     selection_t *sel = NULL;
00625 
00626     if (gh != NULL)
00627         {
00628             sel = (selection_t *) g_malloc0(sizeof(selection_t));
00629 
00630             if (gh->selection.start < gh->selection.end)
00631                 {
00632                     sel->start = gh->selection.start;
00633                     sel->end = gh->selection.end;
00634                 }
00635             else
00636                 {
00637                     sel->end = gh->selection.start;
00638                     sel->start = gh->selection.end;
00639                 }
00640 
00641             return sel;
00642         }
00643     else
00644         {
00645             return NULL;
00646         }
00647 }
00648 
00649 
00650 /**
00651  * Inits a doc_t structure
00652  * @param hex_doc : hex_document but encapsulated in Heraia_Document
00653  *                  structure
00654  * @param hex_widget : Widget to display an hexadecimal view of the file
00655  * @return returns a newly allocated doc_t structure
00656  */
00657 doc_t *new_doc_t(Heraia_Document *hex_doc, GtkWidget *hex_widget)
00658 {
00659     doc_t *new_doc;
00660 
00661     new_doc = (doc_t *) g_malloc0(sizeof(doc_t));
00662 
00663     new_doc->hex_doc = hex_doc;
00664     new_doc->hex_widget = hex_widget;
00665     new_doc->modified = hex_doc->changed; /**@todo do a function to access this value **/
00666 
00667     return new_doc;
00668 }
00669 
00670 
00671 /**
00672  * Closes a previously malloced doc_t structure
00673  * @param current_doc
00674  */
00675 void close_doc_t(doc_t *current_doc)
00676 {
00677 
00678     if (current_doc != NULL)
00679         {
00680             gtk_widget_destroy(current_doc->hex_widget);
00681             g_free(current_doc);
00682         }
00683 }
Generated on Sat Oct 30 18:31:55 2010 for Heraia by  doxygen 1.6.3