/******************************************************************************\ * Copyright (C) 2001, hexcurse is written by Jewfish and Armoth * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * \******************************************************************************/ #include "hex.h" /*******************************************************\ * Description: prints out a line of text to the screen* * the current address line and both the * * hex and decimal values for the current * * lines. It doesn't return anything * \*******************************************************/ void outline(FILE *fp, int linenum) { unsigned int i, c, tmp[BASE]; /* holds char values */ hexList *tmpHead = head; /* tmp linklist head */ for (i = 0; i < BASE; i++) /* set vals to EOF */ tmp[i] = -1; while (tmpHead != NULL && tmpHead->loc < (linenum * BASE)) tmpHead = tmpHead->next; /* advance temp head */ for (i = 0; i < BASE; i++) { while (tmpHead != NULL && (tmpHead->loc < ((linenum * BASE) + i))) tmpHead = tmpHead->next; if (tmpHead != NULL && (tmpHead->loc == ((linenum * BASE) + i))) { /*store val from llist*/ tmp[i] = tmpHead->val; tmpHead = tmpHead->next; } } wclrtoeol(windows->hex); /* clear lines */ wclrtoeol(windows->ascii); /*print line's address*/ wprintw(windows->address, (printHex) ? "%08X ":"%08d ", (linenum * BASE)); rewind(fp); /* reset the file ptr */ fseek(fp, (linenum * BASE), 0); /* set new pos for fp */ for (i = 0; i < BASE && (c = getc(fp)) != EOF; i++) { if (tmp[i] != -1) /* while not EOF */ { c = tmp[i]; /* store val in c */ wattron(windows->ascii, A_BOLD); wattron(windows->hex, A_BOLD); } wprintw(windows->hex, "%02X ", c); /* print out hex char */ if (USE_EBCDIC) wprintw(windows->ascii, "%c", EBCDIC[c]);/* print EBCDIC char */ else /* print ASCII char */ wprintw(windows->ascii, (isprint(c)) ? "%c":".", c); wattroff(windows->ascii, A_BOLD); wattroff(windows->hex, A_BOLD); } } /*******************************************************\ * Description: determines the maximum size of the * * file. It returns the number of chars * * in the file * \*******************************************************/ int maxLoc(FILE *fp) { fseek(fp, 0, SEEK_END); /* seek to end of file*/ return((int)ftell(fp)); /* return val at EOF */ } /******************************************************\ * Description: prints out the command line help info * * this function does not return anything* \******************************************************/ void print_usage() { char *ver = HVERSION; printf("hexcurse, version %s by FishMoth (jewfish and armoth)\n",ver); printf("\nusage: hexcurse [-?|help] [-a] [-r rnum] [-o outputfile] "); printf("[[-i] infile]\n\n"); printf(" -a\t\tOutput addresses in decimal format initially\n"); printf(" -e\t\tOutput characters in EBCDIC format rather than ASCII\n"); printf(" -r rnum\tResize the display to \"rnum\" bytes wide\n"); printf(" -o outfile\tWrite output to outfile by default\n"); printf(" -? | -help\tDisplay usage and version of hexcurse program\n"); printf(" [-i] infile\tRead from data from infile (-i required if not last argument)\n\n"); } /*******************************************************\ * Description: Determines the maximum lines that will * * be displayed in the hexeditor. The * * values is returned as an integer * \******************************************************/ int maxLines(int len) { if (BASE == 0) return(0); /* avoid a div by 0 */ if ((len % BASE) !=0) /* mod len by BASE */ return(len/BASE); /* so extra line wont */ else /* be printed out */ return((BASE==1) ? 0 : (len/BASE - 1)); /* avoid pot div by 0 */ return(len/BASE); } /********************************************************\ * Description: opens file specified at input returning * * non-zero if the file opened correctly * \********************************************************/ int openfile(WINS *win, char *fpINfilename) { char *ch; FILE *tmpfp; /* temp pointer */ ch = (char *) malloc(81); wmove(win->hex_outline, LINES-1, 21); /* output prompt */ wclrtoeol(win->hex_outline); mvwaddstr(win->hex_outline, LINES - 1, 1, "Enter file to open: "); freeList(head); /* free linked list */ head = NULL; if (!fpINfilename) fpINfilename = (char *) malloc(81); /* allocate if NULL */ ch = inputLine(win->hex_outline, LINES - 1, 21); /* get filename */ if (ch[0] == 27) /* if escape was hit */ { restoreBorder(win); /* restore border */ wrefresh(win->hex_outline); /* refresh window */ return FALSE; } if (ch[0] != '\0') strncpy(fpINfilename, ch, 80); if (!(tmpfp = fopen(fpINfilename, "r"))) /* if cannot open... */ { wmove(win->hex_outline, LINES-1, 1); wclrtoeol(win->hex_outline); /* output message */ /*mvwaddstr(win->hex_outline, LINES - 1, 1, "Could not open file");*/ popupWin("Could not open file!", -1); restoreBorder(win); wnoutrefresh(win->hex_outline); /* refresh window */ return FALSE; /* return bad */ } restoreBorder(win); /* restore border */ wrefresh(win->hex_outline); /* refresh window */ fclose(tmpfp); /* close temp pointer */ fpIN = fopen(fpINfilename, "r"); /* open file: read */ wclear(win->hex); /* clear windows */ wclear(win->ascii); wclear(win->address); refreshall(win); /* refresh everything */ doupdate(); /* update screen */ return TRUE; /* return good */ } /********************************************************\ * Description: saves file specified from input, and * * doesn't return anything * \********************************************************/ void savefile(WINS *win, char *fpINfilename, char *fpOUTfilename) { char *ch; /* temp string */ ch = (char *) malloc(81); /* malloc temp string */ if (!fpINfilename) fpINfilename = (char *) malloc(81); /* allocate if NULL */ wmove(win->hex_outline, LINES-1, 20); /* clear line and */ wclrtoeol(win->hex_outline); /* output prompt */ mvwprintw(win->hex_outline, LINES-1, 1, "Enter file to save: %s", (strcmp(fpOUTfilename, "")) ? fpOUTfilename:fpINfilename); wrefresh(win->hex_outline); /* refresh window */ ch = inputLine(win->hex_outline, LINES - 1, 21); /* get filename */ if (ch[0] != 27) /*if escape wasn't hit*/ { if (ch[0] != '\0') /* if string exist... */ strncpy(fpOUTfilename, ch, 80); /* copy into fileout */ /* if infile... */ if (!strncmp(fpOUTfilename, fpINfilename, strlen(fpINfilename))) bzero(fpOUTfilename, strlen(fpOUTfilename)); /* clear string */ /*write to file */ if (!writeChanges(win, fpIN, fpOUT, fpINfilename, fpOUTfilename)) popupWin("The file has been saved.", -1); } free(ch); restoreBorder(win); wnoutrefresh(win->hex_outline); } /********************************************************\ * Description: searches for a series of either hex or * * ascii values of upto 16 bytes long. The* * function returns the next location of * * the specified string or -1 if not found * \********************************************************/ int hexSearch(FILE *fp, int ch[], int startfp, int length) { int loop, tmp, c, flag=0; long int currLoc, startLoc, foundLoc=-1; /* init vars */ fseek(fp, startfp, SEEK_SET); /* begin from loc */ c = getc(fp); /* get char from file */ currLoc = ftell(fp); /* get location */ if ((tmp = searchList(head, currLoc-1)) != -1) /* check for val in ll*/ c = tmp; while (currLoc != startfp) /* while not back to */ { /* beginning... */ if (c == ch[0]) /* if char we want... */ { startLoc = ftell(fp); /* get location */ /* loop to find rest */ for (loop = 1; (loop < length) && (c != EOF); loop++) { c = fgetc(fp); currLoc = ftell(fp); if ((tmp = searchList(head, currLoc-1)) != -1) c = tmp; if (c != ch[loop]) break; } if ((loop == length) && (flag)) /* if found it */ return startLoc - 1; /* return location */ else if (loop == length) foundLoc = startLoc -1; /* return if no others*/ } flag = 1; /* if cursor is on the search string, continue searching */ if (c == EOF) /* if EOF rewind */ rewind(fp); currLoc = ftell(fp); /* current location */ if (currLoc != startfp) /* if not at start... */ { c = fgetc(fp); /* get another char */ currLoc = ftell(fp); if ((tmp = searchList(head, currLoc-1)) != -1) c = tmp; } } return foundLoc; /* return not found */ } char *boyerMooreSearch(FILE *fp, const char str[], int startfp, size_t textLen) { unsigned charJump[AlphabetSize]; unsigned *matchJump; unsigned *backUp; size_t patLen; unsigned u, uText, uPat, uA, uB; char text[97]; /* temporarily created just to make things compile */ patLen = strlen(str); matchJump = (unsigned *) malloc(2 * sizeof (unsigned) * (patLen + 1)); backUp = matchJump + patLen + 1; memset(charJump, 0, AlphabetSize * sizeof(unsigned)); for (u = 0; u < patLen; u++) charJump[((unsigned char) str[u])] = patLen - u - 1; for (u = 1; u <= patLen; u++) matchJump[u] = 2 * patLen - u; u = patLen; uA = patLen + 1; while (u > 0) { backUp[u] = uA; while (uA <= patLen && str[u - 1] != str[uA - 1]) { if (matchJump[uA] > patLen - u) matchJump[uA] = patLen - u; uA = backUp[uA]; } u--; uA--; } for (u = 1; u <= uA; u++) if (matchJump[u] > patLen + uA - u) matchJump[u] = patLen + uA - u; uB = backUp[uA]; while (uA <= patLen) { while (uA <= uB) { if (matchJump[uA] > uB - uA + patLen) matchJump[uA] = uB - uA + patLen; uA++; } uB = backUp[uB]; } uPat = patLen; uText = patLen - 1; while (uText < textLen && uPat != 0) { if (text[uText] == str[uPat - 1]) { uText--; uPat--; } else { uA = charJump[((unsigned char) text[uText])]; uB = matchJump[uPat]; uText += max(uA, uB); uPat = patLen; } } if (uPat == 0) return ((char *)(text + (uText + 1))); else return NULL; } /********************************************************\ * Description: goes to a certain location in the file * * Returns: currentLine (in file) * \********************************************************/ int gotoLine(FILE *fp, int currLoc, int gotoLoc, int maxlines, WINDOW *win) { int count, currentLine, row, col, tmp, linediff; getyx(win, row, col); restoreBorder(windows); /* restore border */ wrefresh(windows->hex_outline); currentLine = maxLines(gotoLoc); if ((gotoLoc % BASE) == 0) currentLine++; /* we must calculate the lines between the currloc and gotoLoc. *\ * we do this by calculating the line number for the value of currloc * * if it was on the first row and substract it from the line number * * of gotoLoc. If it's less then MAXY then it's on the the that * * means the destination is visible on the screen and that the cursor * \* should move to the spot rather then scroll to the position */ if (gotoLoc >= currLoc) /* the destination is below the current loc */ { tmp = currLoc - (row * BASE); linediff=currentLine-((tmp%BASE) ? maxLines(tmp) : maxLines(++tmp)); } else /*the dest is above the current location, must handle differently*/ { tmp = currLoc + ((MAXY - row) * BASE); linediff = currentLine - ((tmp%BASE) ? maxLines(tmp) : maxLines(++tmp)); if (linediff >= (MAXY*-1) && linediff < 1) linediff += MAXY; } if (linediff < 1) linediff *= -1; /* take abs value */ if (linediff <= MAXY) /* if the dest on the same screen as currloc */ { /* now move position w/o scrolling dest line to the top of screen */ wmove((editHex) ? windows->hex : windows->ascii, linediff , (editHex) ? ((gotoLoc % BASE) * 3) : (gotoLoc % BASE)); } else { wclear(windows->hex); /* clear windows */ wclear(windows->ascii); wclear(windows->address); wmove(windows->hex, 0, 0); /*position cursors */ wmove(windows->ascii, 0, 0); wmove(windows->address, 0, 0); /* output lines */ for (count = 0; count <= MAXY && (count + currentLine)<=maxlines; count++) outline(fp, count+currentLine); wmove((editHex) ? windows->hex : windows->ascii, 0, (editHex) ? ((gotoLoc % BASE) * 3) : (gotoLoc % BASE)); /* restore cursor */ } #ifdef DEBUG_GOTO mvwprintw(windows->hex_outline,0,20," "); mvwprintw(windows->hex_outline,0,10,"value:%d location:%d %d %d %d", maxLines(tmp), maxLines(gotoLoc), linediff, gotoLoc, MAXY); #endif wnoutrefresh(windows->scrollbar); /* refresh screen */ wnoutrefresh(windows->ascii); wnoutrefresh(windows->address); wnoutrefresh(windows->hex); doupdate(); /* update screen */ return currentLine; } /********************************************************\ * Description: gets values at given location in file * * Returns: the value at the given location * \********************************************************/ int getLocVal(long loc) { hexList *tmpHead = head; /* tmp linklist head */ while (tmpHead != NULL && (tmpHead->loc < loc)) tmpHead = tmpHead->next; if (tmpHead != NULL && (tmpHead->loc == loc)) return(tmpHead->val); fseek(fpIN, loc, SEEK_SET); /* goto location */ return(fgetc(fpIN)); } /********************************************************\ * Description: checks if a loc is in the linked list * * Returns: returns TRUE if loc is in the llist * \********************************************************/ bool inHexList(long loc) { hexList *tmpHead = head; /* tmp linklist head */ while (tmpHead != NULL && (tmpHead->loc < loc)) tmpHead = tmpHead->next; if (tmpHead != NULL && (tmpHead->loc == loc)) return(TRUE); else return(FALSE); }