Skip to content

Commit f9b03fe

Browse files
Update exploithawk.c
1 parent 0b4cfcd commit f9b03fe

File tree

1 file changed

+119
-41
lines changed

1 file changed

+119
-41
lines changed

exploithawk.c

Lines changed: 119 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
#define _GNU_SOURCE
12
#include <stdio.h>
23
#include <stdlib.h>
34
#include <string.h>
5+
#include <strings.h> // for strcasestr
46
#include <pthread.h>
57
#include <dirent.h>
68
#include <ncurses.h>
@@ -10,7 +12,7 @@
1012
#define MAX_PATH 512
1113
#define MAX_TITLE 512
1214
#define MAX_SOURCE 32
13-
#define TITLE_WRAP 50 // width for title column
15+
#define TITLE_WRAP 50 // preferred width for title column
1416

1517
typedef struct {
1618
char source[MAX_SOURCE];
@@ -53,16 +55,23 @@ const char *exploitDirs[] = {
5355

5456
char search_term[128];
5557

56-
// Check if all ^-separated parts exist in str
58+
59+
static void trim_newline(char *s) {
60+
if (!s) return;
61+
size_t n = strlen(s);
62+
while (n > 0 && (s[n-1] == '\n' || s[n-1] == '\r')) { s[n-1] = '\0'; n--; }
63+
}
64+
65+
// Check if all ^-separated parts exist in str (case-insensitive)
5766
int matches_search(const char *str, const char *term) {
67+
if (!str || !term) return 0;
5868
char tmp[128];
5969
strncpy(tmp, term, sizeof(tmp));
6070
tmp[sizeof(tmp)-1] = 0;
6171

6272
char *part = strtok(tmp, "^");
6373
while (part != NULL) {
64-
char *found = strcasestr(str, part);
65-
if (!found) return 0;
74+
if (!strcasestr(str, part)) return 0;
6675
part = strtok(NULL, "^");
6776
}
6877
return 1;
@@ -83,22 +92,26 @@ void add_result(const char *source, const char *title, const char *path) {
8392
pthread_mutex_unlock(&lock);
8493
}
8594

86-
// CSV thread
95+
8796
void *load_csv_thread(void *arg) {
8897
const char *path = (const char *)arg;
8998
FILE *f = fopen(path, "r");
9099
if (!f) return NULL;
91100

92-
char line[1024];
101+
char line[2048];
93102
while (fgets(line, sizeof(line), f)) {
94103
char *cols[10];
95104
int col = 0;
96105
char *p = strtok(line, ",");
97106
while (p && col < 10) {
107+
while (*p == ' ' || *p == '\t') p++;
108+
trim_newline(p);
98109
cols[col++] = p;
99110
p = strtok(NULL, ",");
100111
}
101112
if (col >= 3 && matches_search(cols[2], search_term)) {
113+
trim_newline(cols[1]);
114+
trim_newline(cols[2]);
102115
add_result("CSV", cols[2], cols[1]);
103116
}
104117
}
@@ -134,22 +147,28 @@ void *scan_dir_thread(void *arg) {
134147
return NULL;
135148
}
136149

137-
138150
int wrap_text(const char *text, char lines[][MAX_TITLE], int width) {
151+
if (!text) {
152+
lines[0][0] = '\0';
153+
return 1;
154+
}
139155
int len = strlen(text);
156+
if (len == 0) {
157+
lines[0][0] = '\0';
158+
return 1;
159+
}
140160
int count = 0;
141161
int i = 0;
142-
while (i < len) {
162+
while (i < len && count < 10) {
143163
int chunk = (len - i > width) ? width : len - i;
144164
strncpy(lines[count], text + i, chunk);
145165
lines[count][chunk] = '\0';
146166
count++;
147167
i += chunk;
148168
}
149-
return count;
169+
return (count == 0) ? 1 : count;
150170
}
151171

152-
153172
void display_results() {
154173
initscr();
155174
noecho();
@@ -159,68 +178,127 @@ void display_results() {
159178
if (has_colors()) {
160179
start_color();
161180
use_colors = 1;
162-
// color pairs
163181
init_pair(1, COLOR_YELLOW, COLOR_BLACK); // source
164182
init_pair(2, COLOR_CYAN, COLOR_BLACK); // title
165183
init_pair(3, COLOR_GREEN, COLOR_BLACK); // path
166184
init_pair(4, COLOR_MAGENTA, COLOR_BLACK); // header
185+
} else {
186+
use_colors = 0;
167187
}
168188

169189
int ch, start = 0, rows, cols;
170190
getmaxyx(stdscr, rows, cols);
171191

172-
int col_source = 12;
173-
int col_title = TITLE_WRAP;
174-
int col_path = cols - col_source - col_title - 5;
192+
193+
int content_source = 10;
194+
int content_title = TITLE_WRAP;
195+
int content_path = cols - (content_source + content_title + 10); // 10 = extra chars from separators/spaces
196+
if (content_path < 10) {
197+
// shrink title to make space, but keep minimum widths
198+
content_title = cols - (content_source + 10 + 10);
199+
if (content_title < 10) content_title = 10;
200+
content_path = cols - (content_source + content_title + 10);
201+
if (content_path < 10) content_path = 10;
202+
}
203+
204+
int x_source_field = 2;
205+
int x_title_field = x_source_field + content_source + 3;
206+
int x_path_field = x_title_field + content_title + 3;
175207

176208
while (1) {
177209
clear();
178210

179-
if (use_colors) attron(COLOR_PAIR(4) | A_BOLD);
180-
mvprintw(0, 0, "| %-10s | %-*s | %-*s |", "Source", col_title, "Title", col_path, "Path");
181-
if (use_colors) attroff(COLOR_PAIR(4) | A_BOLD);
211+
char header_buf[1024];
212+
snprintf(header_buf, sizeof(header_buf),
213+
"| %-*.*s | %-*.*s | %-*.*s |",
214+
content_source, content_source, "Source",
215+
content_title, content_title, "Title",
216+
content_path, content_path, "Path");
217+
218+
// clear header line then print
219+
move(0,0); clrtoeol();
220+
mvprintw(0, 0, "%s", header_buf);
221+
if (use_colors) {
222+
attron(COLOR_PAIR(4) | A_BOLD);
223+
mvprintw(0, x_source_field, "%-*.*s", content_source, content_source, "Source");
224+
mvprintw(0, x_title_field, "%-*.*s", content_title, content_title, "Title");
225+
mvprintw(0, x_path_field, "%-*.*s", content_path, content_path, "Path");
226+
attroff(COLOR_PAIR(4) | A_BOLD);
227+
}
182228

229+
// separator line under header
183230
mvhline(1, 0, '-', cols);
184231

185232
int printed_rows = 0;
186233
for (int i = start; i < result_count && printed_rows < rows - 3; i++) {
187234
char title_lines[10][MAX_TITLE];
188235
char path_lines[10][MAX_PATH];
189-
int title_count = wrap_text(results[i].title, title_lines, col_title);
190-
int path_count = wrap_text(results[i].path, path_lines, col_path);
191-
int max_lines = title_count > path_count ? title_count : path_count;
236+
int title_count = wrap_text(results[i].title, title_lines, content_title);
237+
int path_count = wrap_text(results[i].path, path_lines, content_path);
238+
int max_lines = (title_count > path_count) ? title_count : path_count;
192239

193240
for (int l = 0; l < max_lines && printed_rows < rows - 3; l++) {
194241
int line_y = printed_rows + 2;
195-
196-
// Source column
197-
if (use_colors) attron(COLOR_PAIR(1));
198-
mvprintw(line_y, 0, "| %-10.10s ", l == 0 ? results[i].source : "");
199-
if (use_colors) attroff(COLOR_PAIR(1));
200-
201-
// Title column
202-
if (use_colors) attron(COLOR_PAIR(2));
203-
mvprintw(line_y, 13, "| %-*s ", col_title, l < title_count ? title_lines[l] : "");
204-
if (use_colors) attroff(COLOR_PAIR(2));
205-
206-
// Path column
207-
if (use_colors) attron(COLOR_PAIR(3));
208-
mvprintw(line_y, 15 + col_title, "| %-*s |", col_path, l < path_count ? path_lines[l] : "");
209-
if (use_colors) attroff(COLOR_PAIR(3));
242+
char row_buf[2048];
243+
244+
const char *src_display = (l == 0) ? results[i].source : "";
245+
const char *title_display = (l < title_count) ? title_lines[l] : "";
246+
const char *path_display = (l < path_count) ? path_lines[l] : "";
247+
248+
// build base row string with exact widths
249+
snprintf(row_buf, sizeof(row_buf),
250+
"| %-*.*s | %-*.*s | %-*.*s |",
251+
content_source, content_source, src_display,
252+
content_title, content_title, title_display,
253+
content_path, content_path, path_display);
254+
255+
// clear line then print base row
256+
move(line_y, 0); clrtoeol();
257+
mvprintw(line_y, 0, "%s", row_buf);
258+
259+
if (use_colors) {
260+
// Source
261+
attron(COLOR_PAIR(1));
262+
mvprintw(line_y, x_source_field, "%-*.*s", content_source, content_source, src_display);
263+
attroff(COLOR_PAIR(1));
264+
265+
// Title
266+
attron(COLOR_PAIR(2));
267+
mvprintw(line_y, x_title_field, "%-*.*s", content_title, content_title, title_display);
268+
attroff(COLOR_PAIR(2));
269+
270+
// Path
271+
attron(COLOR_PAIR(3));
272+
mvprintw(line_y, x_path_field, "%-*.*s", content_path, content_path, path_display);
273+
attroff(COLOR_PAIR(3));
274+
}
210275

211276
printed_rows++;
212277
}
213278
}
214279

215-
mvprintw(rows - 1, 0, "Use Up/Down arrows to scroll, q to quit. Showing %d of %d results",
216-
start+1, result_count);
280+
// footer / help line
281+
move(rows - 1, 0); clrtoeol();
282+
mvprintw(rows - 1, 0, "Use Up/Down/PageUp/PageDown arrows to scroll, q to quit. Showing %d of %d results",
283+
(result_count == 0 ? 0 : start + 1), result_count);
284+
217285
refresh();
218286

219287
ch = getch();
220288
if (ch == 'q') break;
221-
else if (ch == KEY_DOWN) { if (start + 1 < result_count) start++; }
222-
else if (ch == KEY_UP) { if (start > 0) start--; }
289+
else if (ch == KEY_DOWN) {
290+
if (start + 1 < result_count) start++;
291+
} else if (ch == KEY_UP) {
292+
if (start > 0) start--;
293+
} else if (ch == KEY_NPAGE) { // page down
294+
start += (rows - 4);
295+
if (start >= result_count) start = (result_count > 0) ? result_count - 1 : 0;
296+
} else if (ch == KEY_PPAGE) { // page up
297+
start -= (rows - 4);
298+
if (start < 0) start = 0;
299+
}
223300
}
301+
224302
endwin();
225303
}
226304

@@ -240,11 +318,11 @@ int main(int argc, char *argv[]) {
240318
pthread_t threads[64];
241319

242320
// CSV threads
243-
for (int i = 0; i < sizeof(exploitDBPaths)/sizeof(exploitDBPaths[0]); i++)
321+
for (int i = 0; i < (int)(sizeof(exploitDBPaths)/sizeof(exploitDBPaths[0])); i++)
244322
pthread_create(&threads[num_threads++], NULL, load_csv_thread, (void*)exploitDBPaths[i]);
245323

246324
// Directory threads
247-
for (int i = 0; i < sizeof(exploitDirs)/sizeof(exploitDirs[0]); i++)
325+
for (int i = 0; i < (int)(sizeof(exploitDirs)/sizeof(exploitDirs[0])); i++)
248326
pthread_create(&threads[num_threads++], NULL, scan_dir_thread, (void*)exploitDirs[i]);
249327

250328
// Join all threads

0 commit comments

Comments
 (0)