2018-02-05 22:05:02 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sqlite3.h>
|
|
|
|
#include "bbs.h"
|
|
|
|
|
|
|
|
extern struct bbs_config conf;
|
2018-02-06 01:41:55 +00:00
|
|
|
extern struct user_record *gUser;
|
2018-02-05 22:05:02 +00:00
|
|
|
|
|
|
|
char *nl_get_bbsname(struct fido_addr *addr, char *domain) {
|
|
|
|
sqlite3 *db;
|
2018-10-08 14:13:11 +00:00
|
|
|
sqlite3_stmt *res;
|
2018-02-05 22:05:02 +00:00
|
|
|
int rc;
|
|
|
|
char buffer[PATH_MAX];
|
|
|
|
char *ret;
|
|
|
|
char *sql_buf = "SELECT bbsname FROM nodelist WHERE nodeno=? AND domain=?";
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-05 22:05:02 +00:00
|
|
|
snprintf(buffer, PATH_MAX, "%s/nodelists.sq3", conf.bbs_path);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-05 22:05:02 +00:00
|
|
|
rc = sqlite3_open(buffer, &db);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-05 22:05:02 +00:00
|
|
|
if (rc != SQLITE_OK) {
|
2018-10-08 14:13:11 +00:00
|
|
|
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
|
|
|
return strdup("Unknown");
|
|
|
|
}
|
2018-02-05 22:05:02 +00:00
|
|
|
sqlite3_busy_timeout(db, 5000);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-05 22:05:02 +00:00
|
|
|
rc = sqlite3_prepare_v2(db, sql_buf, -1, &res, 0);
|
|
|
|
|
|
|
|
if (rc != SQLITE_OK) {
|
|
|
|
sqlite3_close(db);
|
2018-02-06 01:41:55 +00:00
|
|
|
return strdup("Unknown");
|
2018-02-05 22:05:02 +00:00
|
|
|
}
|
|
|
|
|
More use of ptr_vector; avoid unnecessary copies.
Recast more code in terms of the ptr_vector abstraction.
The mail_menu.c code also made a lot of unnecessary copies
of strings. For example, there was this code sequence:
for (i = z; i < lines - 1; i++) {
free(content[i]);
content[i] = strdup(content[i + 1]);
}
free(content[i]);
lines--;
content = (char **)realloc(content, sizeof(char *) * lines);
Here, `content` represents an array of lines of text.
This code is removing an element from somewhere in that
array (possibly in the middle), and then shifting the
remaining elements over one position.
But observe the calls to `free` and `strdup` in the loop
body: the content is already dynamically allocated. We
free whatever was in the selected position, and then make
*another copy* of the data in the next position to put
into the now-available slot in the array: repeat for the
remainder of the array's elements.
Instead, we could change this code to just shift things
down:
free(content[z]);
for (i = z; i < (lines - 1); ++i)
content[i] = content[i + 1];
--lines;
ncontent = realloc(content, sizeof(char *) * lines);
assert(ncontent == NULL);
content = ncontent;
However, the ptr_vector abstraction provides us a function,
`ptr_vector_del` that deletes an element from the array and
returns the pointer, so we can rewrite this as simply:
free(ptr_vector_del(&content, z));
No additional malloc()/free() required, which means less
pressure on the memory allocator and less copying of data.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
|
|
|
if (addr->point != 0) {
|
2018-10-08 14:13:11 +00:00
|
|
|
// no support for point addresses yet.
|
|
|
|
return strdup("Unknown");
|
|
|
|
}
|
More use of ptr_vector; avoid unnecessary copies.
Recast more code in terms of the ptr_vector abstraction.
The mail_menu.c code also made a lot of unnecessary copies
of strings. For example, there was this code sequence:
for (i = z; i < lines - 1; i++) {
free(content[i]);
content[i] = strdup(content[i + 1]);
}
free(content[i]);
lines--;
content = (char **)realloc(content, sizeof(char *) * lines);
Here, `content` represents an array of lines of text.
This code is removing an element from somewhere in that
array (possibly in the middle), and then shifting the
remaining elements over one position.
But observe the calls to `free` and `strdup` in the loop
body: the content is already dynamically allocated. We
free whatever was in the selected position, and then make
*another copy* of the data in the next position to put
into the now-available slot in the array: repeat for the
remainder of the array's elements.
Instead, we could change this code to just shift things
down:
free(content[z]);
for (i = z; i < (lines - 1); ++i)
content[i] = content[i + 1];
--lines;
ncontent = realloc(content, sizeof(char *) * lines);
assert(ncontent == NULL);
content = ncontent;
However, the ptr_vector abstraction provides us a function,
`ptr_vector_del` that deletes an element from the array and
returns the pointer, so we can rewrite this as simply:
free(ptr_vector_del(&content, z));
No additional malloc()/free() required, which means less
pressure on the memory allocator and less copying of data.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
|
|
|
snprintf(buffer, PATH_MAX, "%d:%d/%d", addr->zone, addr->net, addr->node);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
|
|
|
sqlite3_bind_text(res, 1, buffer, -1, 0);
|
|
|
|
sqlite3_bind_text(res, 2, domain, -1, 0);
|
2018-02-05 22:05:02 +00:00
|
|
|
|
|
|
|
if (sqlite3_step(res) != SQLITE_ROW) {
|
|
|
|
sqlite3_finalize(res);
|
|
|
|
sqlite3_close(db);
|
|
|
|
return strdup("Unknown");
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
|
|
|
ret = strdup(sqlite3_column_text(res, 0));
|
2018-02-05 22:05:02 +00:00
|
|
|
|
|
|
|
sqlite3_finalize(res);
|
|
|
|
sqlite3_close(db);
|
|
|
|
return ret;
|
2018-02-06 01:41:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct nl_temp {
|
|
|
|
char *address;
|
|
|
|
char *location;
|
|
|
|
char *sysop;
|
|
|
|
char *bbsname;
|
|
|
|
};
|
|
|
|
|
|
|
|
void nl_browser() {
|
|
|
|
int entry_count = 0;
|
|
|
|
struct nl_temp **entries;
|
More use of ptr_vector; avoid unnecessary copies.
Recast more code in terms of the ptr_vector abstraction.
The mail_menu.c code also made a lot of unnecessary copies
of strings. For example, there was this code sequence:
for (i = z; i < lines - 1; i++) {
free(content[i]);
content[i] = strdup(content[i + 1]);
}
free(content[i]);
lines--;
content = (char **)realloc(content, sizeof(char *) * lines);
Here, `content` represents an array of lines of text.
This code is removing an element from somewhere in that
array (possibly in the middle), and then shifting the
remaining elements over one position.
But observe the calls to `free` and `strdup` in the loop
body: the content is already dynamically allocated. We
free whatever was in the selected position, and then make
*another copy* of the data in the next position to put
into the now-available slot in the array: repeat for the
remainder of the array's elements.
Instead, we could change this code to just shift things
down:
free(content[z]);
for (i = z; i < (lines - 1); ++i)
content[i] = content[i + 1];
--lines;
ncontent = realloc(content, sizeof(char *) * lines);
assert(ncontent == NULL);
content = ncontent;
However, the ptr_vector abstraction provides us a function,
`ptr_vector_del` that deletes an element from the array and
returns the pointer, so we can rewrite this as simply:
free(ptr_vector_del(&content, z));
No additional malloc()/free() required, which means less
pressure on the memory allocator and less copying of data.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
|
|
|
struct ptr_vector vec;
|
2018-02-06 01:41:55 +00:00
|
|
|
sqlite3 *db;
|
2018-10-08 14:13:11 +00:00
|
|
|
sqlite3_stmt *res;
|
2018-02-06 01:41:55 +00:00
|
|
|
int rc;
|
|
|
|
char buffer[PATH_MAX];
|
|
|
|
char *ret;
|
|
|
|
char *sql_buf = "SELECT nodeno,location,sysop,bbsname FROM nodelist WHERE domain=?";
|
|
|
|
int i;
|
|
|
|
int redraw = 1;
|
|
|
|
int start = 0;
|
|
|
|
int selected = 0;
|
|
|
|
char c;
|
|
|
|
|
|
|
|
// load nodelist
|
|
|
|
snprintf(buffer, PATH_MAX, "%s/nodelists.sq3", conf.bbs_path);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-06 01:41:55 +00:00
|
|
|
rc = sqlite3_open(buffer, &db);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-06 01:41:55 +00:00
|
|
|
if (rc != SQLITE_OK) {
|
2018-10-08 14:13:11 +00:00
|
|
|
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
|
|
|
return;
|
|
|
|
}
|
2018-02-06 01:41:55 +00:00
|
|
|
sqlite3_busy_timeout(db, 5000);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-06 01:41:55 +00:00
|
|
|
rc = sqlite3_prepare_v2(db, sql_buf, -1, &res, 0);
|
|
|
|
|
|
|
|
if (rc != SQLITE_OK) {
|
|
|
|
sqlite3_close(db);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
sqlite3_bind_text(res, 1, conf.mail_conferences[gUser->cur_mail_conf]->domain, -1, 0);
|
|
|
|
|
More use of ptr_vector; avoid unnecessary copies.
Recast more code in terms of the ptr_vector abstraction.
The mail_menu.c code also made a lot of unnecessary copies
of strings. For example, there was this code sequence:
for (i = z; i < lines - 1; i++) {
free(content[i]);
content[i] = strdup(content[i + 1]);
}
free(content[i]);
lines--;
content = (char **)realloc(content, sizeof(char *) * lines);
Here, `content` represents an array of lines of text.
This code is removing an element from somewhere in that
array (possibly in the middle), and then shifting the
remaining elements over one position.
But observe the calls to `free` and `strdup` in the loop
body: the content is already dynamically allocated. We
free whatever was in the selected position, and then make
*another copy* of the data in the next position to put
into the now-available slot in the array: repeat for the
remainder of the array's elements.
Instead, we could change this code to just shift things
down:
free(content[z]);
for (i = z; i < (lines - 1); ++i)
content[i] = content[i + 1];
--lines;
ncontent = realloc(content, sizeof(char *) * lines);
assert(ncontent == NULL);
content = ncontent;
However, the ptr_vector abstraction provides us a function,
`ptr_vector_del` that deletes an element from the array and
returns the pointer, so we can rewrite this as simply:
free(ptr_vector_del(&content, z));
No additional malloc()/free() required, which means less
pressure on the memory allocator and less copying of data.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
|
|
|
init_ptr_vector(&vec);
|
2018-02-06 01:41:55 +00:00
|
|
|
while (sqlite3_step(res) == SQLITE_ROW) {
|
More use of ptr_vector; avoid unnecessary copies.
Recast more code in terms of the ptr_vector abstraction.
The mail_menu.c code also made a lot of unnecessary copies
of strings. For example, there was this code sequence:
for (i = z; i < lines - 1; i++) {
free(content[i]);
content[i] = strdup(content[i + 1]);
}
free(content[i]);
lines--;
content = (char **)realloc(content, sizeof(char *) * lines);
Here, `content` represents an array of lines of text.
This code is removing an element from somewhere in that
array (possibly in the middle), and then shifting the
remaining elements over one position.
But observe the calls to `free` and `strdup` in the loop
body: the content is already dynamically allocated. We
free whatever was in the selected position, and then make
*another copy* of the data in the next position to put
into the now-available slot in the array: repeat for the
remainder of the array's elements.
Instead, we could change this code to just shift things
down:
free(content[z]);
for (i = z; i < (lines - 1); ++i)
content[i] = content[i + 1];
--lines;
ncontent = realloc(content, sizeof(char *) * lines);
assert(ncontent == NULL);
content = ncontent;
However, the ptr_vector abstraction provides us a function,
`ptr_vector_del` that deletes an element from the array and
returns the pointer, so we can rewrite this as simply:
free(ptr_vector_del(&content, z));
No additional malloc()/free() required, which means less
pressure on the memory allocator and less copying of data.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
|
|
|
struct nl_temp *entry = (struct nl_temp *)malloz(sizeof(struct nl_temp));
|
|
|
|
entry->address = strdup(sqlite3_column_text(res, 0));
|
|
|
|
entry->location = strdup(sqlite3_column_text(res, 1));
|
|
|
|
entry->sysop = strdup(sqlite3_column_text(res, 2));
|
|
|
|
entry->bbsname = strdup(sqlite3_column_text(res, 3));
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
More use of ptr_vector; avoid unnecessary copies.
Recast more code in terms of the ptr_vector abstraction.
The mail_menu.c code also made a lot of unnecessary copies
of strings. For example, there was this code sequence:
for (i = z; i < lines - 1; i++) {
free(content[i]);
content[i] = strdup(content[i + 1]);
}
free(content[i]);
lines--;
content = (char **)realloc(content, sizeof(char *) * lines);
Here, `content` represents an array of lines of text.
This code is removing an element from somewhere in that
array (possibly in the middle), and then shifting the
remaining elements over one position.
But observe the calls to `free` and `strdup` in the loop
body: the content is already dynamically allocated. We
free whatever was in the selected position, and then make
*another copy* of the data in the next position to put
into the now-available slot in the array: repeat for the
remainder of the array's elements.
Instead, we could change this code to just shift things
down:
free(content[z]);
for (i = z; i < (lines - 1); ++i)
content[i] = content[i + 1];
--lines;
ncontent = realloc(content, sizeof(char *) * lines);
assert(ncontent == NULL);
content = ncontent;
However, the ptr_vector abstraction provides us a function,
`ptr_vector_del` that deletes an element from the array and
returns the pointer, so we can rewrite this as simply:
free(ptr_vector_del(&content, z));
No additional malloc()/free() required, which means less
pressure on the memory allocator and less copying of data.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
2018-10-10 17:50:37 +00:00
|
|
|
entry_count = ptr_vector_len(&vec);
|
|
|
|
entries == (struct nl_temp **)consume_ptr_vector(&vec);
|
|
|
|
|
2018-10-08 14:13:11 +00:00
|
|
|
sqlite3_finalize(res);
|
2018-02-06 01:41:55 +00:00
|
|
|
sqlite3_close(db);
|
2018-10-08 14:13:11 +00:00
|
|
|
|
2018-02-06 01:56:33 +00:00
|
|
|
if (entry_count == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-06 01:41:55 +00:00
|
|
|
while (1) {
|
|
|
|
if (redraw) {
|
|
|
|
s_printf("\e[2J\e[1;1H");
|
|
|
|
s_printf(get_string(145));
|
|
|
|
s_printf(get_string(146));
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = start; i < start + 22 && i < entry_count; i++) {
|
2018-02-06 01:41:55 +00:00
|
|
|
if (i == selected) {
|
|
|
|
s_printf(get_string(147), i - start + 2, i, entries[i]->address, entries[i]->bbsname);
|
|
|
|
} else {
|
2018-02-06 01:51:08 +00:00
|
|
|
s_printf(get_string(261), i - start + 2, i, entries[i]->address, entries[i]->bbsname);
|
2018-02-06 01:41:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
s_printf("\e[%d;5H", selected - start + 2);
|
|
|
|
redraw = 0;
|
|
|
|
}
|
|
|
|
c = s_getchar();
|
|
|
|
if (tolower(c) == 'q') {
|
|
|
|
break;
|
|
|
|
} else if (c == 27) {
|
|
|
|
c = s_getchar();
|
|
|
|
if (c == 91) {
|
|
|
|
c = s_getchar();
|
|
|
|
if (c == 66) {
|
|
|
|
// down
|
|
|
|
if (selected + 1 >= start + 22) {
|
|
|
|
start += 22;
|
|
|
|
if (start >= entry_count) {
|
|
|
|
start = entry_count - 22;
|
|
|
|
}
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
selected++;
|
|
|
|
if (selected >= entry_count) {
|
|
|
|
selected = entry_count - 1;
|
|
|
|
} else {
|
2018-10-08 14:13:11 +00:00
|
|
|
if (!redraw) {
|
2018-02-06 01:51:08 +00:00
|
|
|
s_printf(get_string(261), selected - start + 1, selected - 1, entries[selected - 1]->address, entries[selected - 1]->bbsname);
|
2018-02-06 01:41:55 +00:00
|
|
|
s_printf(get_string(147), selected - start + 2, selected, entries[selected]->address, entries[selected]->bbsname);
|
|
|
|
s_printf("\e[%d;5H", selected - start + 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (c == 65) {
|
|
|
|
// up
|
|
|
|
if (selected - 1 < start) {
|
|
|
|
start -= 22;
|
|
|
|
if (start < 0) {
|
|
|
|
start = 0;
|
|
|
|
}
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
selected--;
|
|
|
|
if (selected < 0) {
|
|
|
|
selected = 0;
|
|
|
|
} else {
|
2018-10-08 14:13:11 +00:00
|
|
|
if (!redraw) {
|
2018-02-06 01:41:55 +00:00
|
|
|
s_printf(get_string(147), selected - start + 2, selected, entries[selected]->address, entries[selected]->bbsname);
|
2018-02-06 01:51:08 +00:00
|
|
|
s_printf(get_string(261), selected - start + 3, selected + 1, entries[selected + 1]->address, entries[selected + 1]->bbsname);
|
2018-02-06 01:41:55 +00:00
|
|
|
s_printf("\e[%d;5H", selected - start + 2);
|
2018-10-08 14:13:11 +00:00
|
|
|
}
|
2018-02-06 01:41:55 +00:00
|
|
|
}
|
|
|
|
} else if (c == 75) {
|
|
|
|
// END KEY
|
|
|
|
selected = entry_count - 1;
|
|
|
|
start = entry_count - 22;
|
|
|
|
if (start < 0) {
|
|
|
|
start = 0;
|
|
|
|
}
|
|
|
|
redraw = 1;
|
|
|
|
} else if (c == 72) {
|
|
|
|
// HOME KEY
|
|
|
|
selected = 0;
|
|
|
|
start = 0;
|
|
|
|
redraw = 1;
|
|
|
|
} else if (c == 86 || c == '5') {
|
|
|
|
if (c == '5') {
|
|
|
|
s_getchar();
|
|
|
|
}
|
|
|
|
// PAGE UP
|
|
|
|
selected = selected - 22;
|
|
|
|
if (selected < 0) {
|
|
|
|
selected = 0;
|
|
|
|
}
|
|
|
|
start = selected;
|
|
|
|
redraw = 1;
|
|
|
|
} else if (c == 85 || c == '6') {
|
|
|
|
if (c == '6') {
|
|
|
|
s_getchar();
|
|
|
|
}
|
|
|
|
// PAGE DOWN
|
|
|
|
selected = selected + 22;
|
|
|
|
if (selected >= entry_count) {
|
2018-10-08 14:13:11 +00:00
|
|
|
selected = entry_count - 1;
|
2018-02-06 01:41:55 +00:00
|
|
|
}
|
|
|
|
start = selected;
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (c == 13) {
|
|
|
|
s_printf("\e[2J\e[1;1H");
|
|
|
|
s_printf(get_string(262), entries[selected]->address);
|
|
|
|
s_printf(get_string(263));
|
|
|
|
s_printf(get_string(264), entries[selected]->bbsname);
|
|
|
|
s_printf(get_string(265), entries[selected]->sysop);
|
|
|
|
s_printf(get_string(266), entries[selected]->location);
|
|
|
|
s_printf(get_string(267));
|
|
|
|
s_printf(get_string(185));
|
|
|
|
s_getc();
|
2018-10-08 14:13:11 +00:00
|
|
|
s_printf("\r\n");
|
2018-02-06 01:41:55 +00:00
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
}
|
2018-10-08 14:13:11 +00:00
|
|
|
for (i = 0; i < entry_count; i++) {
|
2018-02-06 01:41:55 +00:00
|
|
|
free(entries[i]->address);
|
|
|
|
free(entries[i]->bbsname);
|
|
|
|
free(entries[i]->sysop);
|
|
|
|
free(entries[i]->location);
|
|
|
|
free(entries[i]);
|
|
|
|
}
|
|
|
|
free(entries);
|
2018-10-09 15:55:13 +00:00
|
|
|
}
|