diff --git a/src/www_files.c b/src/www_files.c
index 53789cd..44f4b2c 100644
--- a/src/www_files.c
+++ b/src/www_files.c
@@ -11,59 +11,64 @@ extern struct bbs_config conf;
extern struct user_record *gUser;
extern char *aha(char *input);
-static char *www_decode(char *clean_url) {
- char *url = (char *)malloz(strlen(clean_url) + 1);
- int i;
- int j = 0;
- unsigned char c;
- if (clean_url == NULL) {
- free(url);
- return NULL;
- }
+static int digit2nibble(int digit) {
+ static const char *const hex = "0123456789abcdef";
+ static const char *const Hex = "0123456789ABCDEF";
- for (i = 0; i < strlen(clean_url); i++) {
- if (clean_url[i] == '%') {
- c = clean_url[i + 1] * 16 + clean_url[i + 2];
- url[j++] = (char)c;
- url[j] = '\0';
- i += 2;
- } else {
- url[j++] = clean_url[i];
- url[j] = '\0';
- }
- }
-
- return url;
+ char *p;
+ p = strchr(hex, digit);
+ if (p != NULL)
+ return p - hex;
+ p = strchr(Hex, digit);
+ if (p != NULL)
+ return p - Hex;
+ return -1;
}
-static char *www_encode(char *url) {
- char *clean_url = (char *)malloz(strlen(url) * 3 + 1);
- int i;
- int j;
+static char *www_decode(char *clean_url) {
+ stralloc url = EMPTY_STRALLOC;
- if (url == NULL) {
- free(clean_url);
- return NULL;
- }
-
- j = 0;
- memset(clean_url, 0, strlen(url) * 3);
-
- for (i = 0; i < strlen(url); i++) {
- if (isalnum(url[i]) || url[i] == '~' || url[i] == '.' || url[i] == '_') {
- sprintf(&clean_url[j], "%c", url[i]);
- j++;
- } else {
- sprintf(&clean_url[j], "%%%02X", url[i]);
- j += 3;
+ assert(clean_url != NULL);
+ for (char *s = clean_url; *s != '\0'; ++s) {
+ if (*s == '+')
+ stralloc_append1(&url, ' ');
+ else if (*s != '%')
+ stralloc_append1(&url, *s);
+ else {
+ int hn = 0, ln = 0, ch = 0;
+ if (s[1] == '\0' || (hn = digit2nibble(s[1])) < 0) {
+ free(url.s);
+ return NULL;
+ }
+ if (s[2] == '\0' || (ln = digit2nibble(s[2])) < 0) {
+ free(url.s);
+ return NULL;
+ }
+ stralloc_append1(&url, hn * 16 + ln);
}
}
+ stralloc_0(&url);
- return clean_url;
+ return url.s;
+}
+
+static void www_encode(stralloc *clean, char *url) {
+ assert(clean != NULL);
+ assert(url != NULL);
+ for (char *s = url; *s != '\0'; ++s) {
+ if (isalnum(*s) || *s == '~' || *s == '.' || *s == '_')
+ stralloc_append1(clean, *s);
+ else if (*s == ' ')
+ stralloc_append1(clean, '+');
+ else {
+ stralloc_append1(clean, '%');
+ stralloc_cat_Byte(clean, *s);
+ }
+ }
}
void www_expire_old_links() {
- char buffer[PATH_MAX];
+ char pathbuf[PATH_MAX];
sqlite3 *db;
sqlite3_stmt *res;
int rc;
@@ -71,9 +76,9 @@ void www_expire_old_links() {
char *ret;
time_t now = time(NULL);
- snprintf(buffer, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path);
+ snprintf(pathbuf, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path);
- rc = sqlite3_open(buffer, &db);
+ rc = sqlite3_open(pathbuf, &db);
if (rc != SQLITE_OK) {
dolog("Cannot open database: %s", sqlite3_errmsg(db));
return;
@@ -91,14 +96,14 @@ void www_expire_old_links() {
}
int www_check_hash_expired(char *hash) {
- char buffer[PATH_MAX];
+ char pathbuf[PATH_MAX];
sqlite3 *db;
sqlite3_stmt *res;
int rc;
time_t now = time(NULL);
char sql[] = "select id from wwwhash where hash = ? and expiry > ?";
- snprintf(buffer, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path);
- rc = sqlite3_open(buffer, &db);
+ snprintf(pathbuf, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path);
+ rc = sqlite3_open(pathbuf, &db);
if (rc != SQLITE_OK) {
return 1;
}
@@ -123,7 +128,7 @@ int www_check_hash_expired(char *hash) {
}
void www_add_hash_to_db(char *hash, time_t expiry) {
- char buffer[PATH_MAX];
+ char pathbuf[PATH_MAX];
sqlite3 *db;
sqlite3_stmt *res;
int rc;
@@ -135,9 +140,9 @@ void www_add_hash_to_db(char *hash, time_t expiry) {
char *ret;
char *err_msg = 0;
- snprintf(buffer, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path);
+ snprintf(pathbuf, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path);
- rc = sqlite3_open(buffer, &db);
+ rc = sqlite3_open(pathbuf, &db);
if (rc != SQLITE_OK) {
return;
}
@@ -195,7 +200,7 @@ char *www_decode_hash(char *hash) {
unsigned long long numbers[4];
int dir, sub, fid, uid;
hashids_t *hashids = hashids_init(conf.bbs_name);
- char buffer[PATH_MAX];
+ char pathbuf[PATH_MAX];
sqlite3 *db;
sqlite3_stmt *res;
int rc;
@@ -222,8 +227,8 @@ char *www_decode_hash(char *hash) {
}
// get filename from database
- snprintf(buffer, PATH_MAX, "%s/%s.sq3", conf.bbs_path, conf.file_directories[dir]->file_subs[sub]->database);
- rc = sqlite3_open(buffer, &db);
+ snprintf(pathbuf, PATH_MAX, "%s/%s.sq3", conf.bbs_path, conf.file_directories[dir]->file_subs[sub]->database);
+ rc = sqlite3_open(pathbuf, &db);
if (rc != SQLITE_OK) {
return NULL;
}
@@ -280,10 +285,8 @@ char *www_create_link(int dir, int sub, int fid) {
return ret;
}
char *www_files_display_listing(int dir, int sub) {
- char *page;
- int max_len;
- int len;
- char buffer[4096];
+ stralloc page = EMPTY_STRALLOC;
+ char pathbuf[PATH_MAX];
char *sql = "select id, filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY filename";
char *filename;
char c;
@@ -296,178 +299,118 @@ char *www_files_display_listing(int dir, int sub) {
int i;
char *clean_url;
- page = (char *)malloz(4096);
- max_len = 4096;
- len = 0;
+ stralloc_copys(&page, "
\n");
- snprintf(buffer, 4096, "\n", conf.file_directories[dir]->name, conf.file_directories[dir]->file_subs[sub]->name);
- if (len + strlen(buffer) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
- }
- strcat(page, buffer);
- len += strlen(buffer);
-
- snprintf(buffer, 4096, "%s/%s.sq3", conf.bbs_path, conf.file_directories[dir]->file_subs[sub]->database);
-
- rc = sqlite3_open(buffer, &db);
+ snprintf(pathbuf, sizeof pathbuf, "%s/%s.sq3",
+ conf.bbs_path, conf.file_directories[dir]->file_subs[sub]->database);
+ rc = sqlite3_open(pathbuf, &db);
if (rc != SQLITE_OK) {
- free(page);
+ free(page.s);
return NULL;
}
sqlite3_busy_timeout(db, 5000);
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
if (rc != SQLITE_OK) {
sqlite3_close(db);
- free(page);
+ free(page.s);
return NULL;
}
- snprintf(buffer, 4096, "Filename | Size | Description |
\n");
- if (len + strlen(buffer) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
- }
- strcat(page, buffer);
- len += strlen(buffer);
-
+ stralloc_cats(&page, "Filename | Size | Description |
\n");
while (sqlite3_step(res) == SQLITE_ROW) {
- filename = strdup(sqlite3_column_text(res, 1));
- clean_url = www_encode(basename(filename));
- snprintf(buffer, 4096, "%s | ", conf.www_url, dir, sub, basename(clean_url), basename(filename));
- free(clean_url);
- free(filename);
- if (len + strlen(buffer) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
- }
- strcat(page, buffer);
- len += strlen(buffer);
+ filename = strdup((char *)sqlite3_column_text(res, 1));
+ char *base_filename = basename(filename);
+ stralloc_cats(&page, "
");
+ stralloc_cats(&page, base_filename);
+ stralloc_cats(&page, " | ");
size = sqlite3_column_int(res, 3);
-
- if (size > 1024 * 1024 * 1024) {
- size = size / 1024 / 1024 / 1024;
- c = 'G';
- } else if (size > 1024 * 1024) {
- size = size / 1024 / 1024;
- c = 'M';
- } else if (size > 1024) {
- size = size / 1024;
+ stralloc_cats(&page, "");
+ int c = 'b';
+ if (size > 1024) {
+ size /= 1024;
c = 'K';
- } else {
- c = 'b';
}
-
- snprintf(buffer, 4096, " | %d%c | ", size, c);
- if (len + strlen(buffer) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
+ if (size > 1024) {
+ size /= 1024;
+ c = 'M';
}
- strcat(page, buffer);
- len += strlen(buffer);
+ if (size > 1024) {
+ size /= 1024;
+ c = 'G';
+ }
+ stralloc_cat_long(&page, size);
+ stralloc_append1(&page, c);
+ stralloc_cats(&page, "");
+ stralloc_cats(&page, "");
description = strdup((char *)sqlite3_column_text(res, 2));
-
- for (i = 0; i < strlen(description); i++) {
- if (description[i] == '\n') {
- description[i] = '\r';
- }
+ for (char *p = description; *p != '\0'; ++p) {
+ if (*p == '\n')
+ *p = '\r';
}
-
- snprintf(buffer, 4096, " | ");
- if (len + strlen(buffer) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
- }
- strcat(page, buffer);
- len += strlen(buffer);
-
aha_out = aha(description);
-
- while (len + strlen(aha_out) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
- }
- strcat(page, aha_out);
- len += strlen(aha_out);
-
+ stralloc_cats(&page, aha_out);
free(aha_out);
free(description);
+ free(filename);
- snprintf(buffer, 4096, " |
\n");
- if (len + strlen(buffer) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
- }
- strcat(page, buffer);
- len += strlen(buffer);
+ stralloc_cats(&page, "\n");
}
-
- snprintf(buffer, 4096, "
\n");
- if (len + strlen(buffer) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
- }
- strcat(page, buffer);
- len += strlen(buffer);
+ stralloc_cats(&page, "
\n");
+ stralloc_0(&page);
sqlite3_finalize(res);
sqlite3_close(db);
- return page;
+ return page.s;
}
char *www_files_areas() {
- char *page;
- int max_len;
- int len;
- char buffer[4096];
- int i;
- int j;
+ stralloc page = EMPTY_STRALLOC;
- page = (char *)malloz(4096);
- max_len = 4096;
- len = 0;
-
- sprintf(buffer, "\n");
- if (len + strlen(buffer) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
- }
- strcat(page, buffer);
- len += strlen(buffer);
-
- for (i = 0; i < conf.file_directory_count; i++) {
- if (conf.file_directories[i]->display_on_web) {
- sprintf(buffer, "%s
\n", conf.file_directories[i]->name);
- if (len + strlen(buffer) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
- }
- strcat(page, buffer);
- len += strlen(buffer);
- for (j = 0; j < conf.file_directories[i]->file_sub_count; j++) {
- sprintf(buffer, "\n", conf.www_url, i, j, conf.file_directories[i]->file_subs[j]->name);
- if (len + strlen(buffer) > max_len - 1) {
- max_len += 4096;
- page = (char *)realloc(page, max_len);
- }
- strcat(page, buffer);
- len += strlen(buffer);
- }
+ stralloc_copys(&page, "\n");
+ for (int i = 0; i < conf.file_directory_count; i++) {
+ if (!conf.file_directories[i]->display_on_web)
+ continue;
+ stralloc_cats(&page, "");
+ stralloc_cats(&page, conf.file_directories[i]->name);
+ stralloc_cats(&page, "
\n");
+ for (int j = 0; j < conf.file_directories[i]->file_sub_count; j++) {
+ stralloc_cats(&page, "\n");
}
}
+ stralloc_0(&page);
- return page;
+ return page.s;
}
char *www_files_get_from_area(int dir, int sub, char *clean_file) {
char *sql = "SELECT filename FROM files WHERE approved=1 AND filename LIKE ? ESCAPE \"^\"";
- char *filenamelike;
+ stralloc filenamelike = EMPTY_STRALLOC;
sqlite3 *db;
sqlite3_stmt *res;
int rc;
- char buffer[PATH_MAX];
+ char pathbuf[PATH_MAX];
char *ret = NULL;
int i;
int extra = 0;
@@ -475,67 +418,35 @@ char *www_files_get_from_area(int dir, int sub, char *clean_file) {
char *file;
file = www_decode(clean_file);
-
- for (i = 0; i < strlen(file); i++) {
- if (file[i] == '^' || file[i] == '%' || file[i] == '_') {
- extra++;
- }
+ stralloc_copys(&filenamelike, "%");
+ for (char *p = file; *p != '\0'; ++p) {
+ if (*p == '^' || *p == '_' || *p == '%')
+ stralloc_append1(&filenamelike, '^');
+ stralloc_append1(&filenamelike, *p);
}
-
- filenamelike = (char *)malloz(strlen(file) + 3 + extra);
-
- i = 0;
- filenamelike[i++] = '%';
- filenamelike[i] = '\0';
-
- for (j = 0; j < strlen(file); j++) {
- switch (file[j]) {
- case '^':
- filenamelike[i++] = '^';
- filenamelike[i++] = '^';
- filenamelike[i] = '\0';
- break;
- case '_':
- filenamelike[i++] = '^';
- filenamelike[i++] = '_';
- filenamelike[i] = '\0';
- break;
- case '%':
- filenamelike[i++] = '^';
- filenamelike[i++] = '%';
- filenamelike[i] = '\0';
- break;
- default:
- filenamelike[i++] = file[j];
- filenamelike[i] = '\0';
- break;
- }
- }
-
- // sprintf(filenamelike, "%%/%s", file);
-
+ stralloc_0(&filenamelike);
free(file);
- snprintf(buffer, PATH_MAX, "%s/%s.sq3", conf.bbs_path, conf.file_directories[dir]->file_subs[sub]->database);
-
- rc = sqlite3_open(buffer, &db);
+ snprintf(pathbuf, PATH_MAX, "%s/%s.sq3", conf.bbs_path, conf.file_directories[dir]->file_subs[sub]->database);
+ rc = sqlite3_open(pathbuf, &db);
if (rc != SQLITE_OK) {
+ free(filenamelike.s);
return NULL;
}
sqlite3_busy_timeout(db, 5000);
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
if (rc != SQLITE_OK) {
sqlite3_close(db);
+ free(filenamelike.s);
return NULL;
}
- sqlite3_bind_text(res, 1, filenamelike, -1, 0);
-
+ sqlite3_bind_text(res, 1, filenamelike.s, -1, 0);
rc = sqlite3_step(res);
if (rc == SQLITE_ROW) {
ret = strdup(sqlite3_column_text(res, 0));
}
- free(filenamelike);
+ free(filenamelike.s);
sqlite3_finalize(res);
sqlite3_close(db);
return ret;