diff --git a/utils/filecenter/filecenter.h b/utils/filecenter/filecenter.h index bdf088a..92248d2 100644 --- a/utils/filecenter/filecenter.h +++ b/utils/filecenter/filecenter.h @@ -18,4 +18,11 @@ struct file_directory { struct file_sub **file_subs; }; +struct archiver { + char *name; + char *extension; + char *unpack; + char *pack; +}; + #endif diff --git a/utils/filecenter/main.c b/utils/filecenter/main.c index 9593187..aba99a7 100644 --- a/utils/filecenter/main.c +++ b/utils/filecenter/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include "../../src/inih/ini.h" @@ -17,6 +18,7 @@ struct files { struct file_directory **file_directories; int file_directory_count = 0; CDKSCREEN *cdkscreen = 0; +char *bbspath; char *configpath; int current_dir; @@ -26,12 +28,59 @@ struct files **f; int fcount = 0; char **filenames; +struct archiver **archivers; +int archiver_count = 0; + +static int archiver_config_handler(void* user, const char* section, const char* name, + const char* value) +{ + int i; + + for (i=0;iname, section) == 0) { + // found it + if (strcasecmp(name, "extension") == 0) { + archivers[i]->extension = strdup(value); + } else if (strcasecmp(name, "unpack") == 0) { + archivers[i]->unpack = strdup(value); + } else if (strcasecmp(name, "pack") == 0) { + archivers[i]->pack = strdup(value); + } + return 1; + } + } + + if (archiver_count == 0) { + archivers = (struct archiver **)malloc(sizeof(struct archiver *)); + } else { + archivers = (struct archiver **)realloc(archivers, sizeof(struct archiver *) * (archiver_count + 1)); + } + + archivers[archiver_count] = (struct archiver *)malloc(sizeof(struct archiver)); + + archivers[archiver_count]->name = strdup(section); + + if (strcasecmp(name, "extension") == 0) { + archivers[archiver_count]->extension = strdup(value); + } else if (strcasecmp(name, "unpack") == 0) { + archivers[archiver_count]->unpack = strdup(value); + } else if (strcasecmp(name, "pack") == 0) { + archivers[archiver_count]->pack = strdup(value); + } + archiver_count++; + + return 1; +} + static int bbs_cfg_handler(void *user, const char* section, const char* name, const char *value) { if (strcasecmp(section, "paths") == 0) { if (strcasecmp(name, "bbs path") == 0) { - configpath = strdup(value); + bbspath = strdup(value); } + if (strcasecmp(name, "config path") == 0) { + configpath = strdup(value); + } } if (strcasecmp(section, "file directories") == 0) { if (file_directory_count == 0) { @@ -113,7 +162,7 @@ static void doApprove(int index) { sqlite3 *db; char database[PATH_MAX]; - snprintf(database, PATH_MAX, "%s/%s.sq3", configpath, file_directories[current_dir]->file_subs[current_sub]->database); + snprintf(database, PATH_MAX, "%s/%s.sq3", bbspath, file_directories[current_dir]->file_subs[current_sub]->database); // populate scroll list rc = sqlite3_open(database, &db); @@ -149,7 +198,7 @@ static void doDisapprove(int index) { struct stat s; char database[PATH_MAX]; - snprintf(database, PATH_MAX, "%s/%s.sq3", configpath, file_directories[current_dir]->file_subs[current_sub]->database); + snprintf(database, PATH_MAX, "%s/%s.sq3", bbspath, file_directories[current_dir]->file_subs[current_sub]->database); // populate scroll list rc = sqlite3_open(database, &db); @@ -195,7 +244,7 @@ static int deleteFile(EObjectType cdktype, void *object, void *clientData, chtyp return FALSE; } - snprintf(database, PATH_MAX, "%s/%s.sq3", configpath, file_directories[current_dir]->file_subs[current_sub]->database); + snprintf(database, PATH_MAX, "%s/%s.sq3", bbspath, file_directories[current_dir]->file_subs[current_sub]->database); rc = sqlite3_open(database, &db); @@ -274,6 +323,264 @@ static int approveFile(EObjectType cdktype, void *object, void *clientData, chty return FALSE; } +int recursive_delete(const char *dir) { + int ret = 0; + FTS *ftsp = NULL; + FTSENT *curr; + + char *files[] = { (char *) dir, NULL }; + + ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL); + if (!ftsp) { + ret = -1; + goto finish; + } + + while ((curr = fts_read(ftsp))) { + switch (curr->fts_info) { + case FTS_NS: + case FTS_DNR: + case FTS_ERR: + break; + + case FTS_DC: + case FTS_DOT: + case FTS_NSOK: + break; + + case FTS_D: + break; + + case FTS_DP: + case FTS_F: + case FTS_SL: + case FTS_SLNONE: + case FTS_DEFAULT: + if (remove(curr->fts_accpath) < 0) { + ret = -1; + } + break; + } + } + +finish: + if (ftsp) { + fts_close(ftsp); + } + + return ret; +} + +static int scanFiles(EObjectType cdktype, void *object, void *clientData, chtype input) { + DIR *ind = opendir(file_directories[current_dir]->file_subs[current_sub]->upload_path); + FILE *fptr; + struct dirent *dent; + int i; + int j; + int bpos; + int gotdesc = 0; + char buffer[PATH_MAX]; + int found; + char *description; + char addfilesql[] = "INSERT INTO files (filename, description, size, dlcount, uploaddate, approved) VALUES(?, ?, ?, 0, ?, 0)"; + char database[PATH_MAX]; + sqlite3 *db; + int rc; + sqlite3_stmt *res; + struct stat st; + int fdate; + int len; + CDKSCROLL *s = (CDKSCROLL *)object; + + if (!ind) { + return FALSE; + } + + while ((dent = readdir(ind)) != NULL) { + if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) { + continue; + } + + sprintf(buffer, "%s/%s", file_directories[current_dir]->file_subs[current_sub]->upload_path, dent->d_name); + + stat(buffer, &st); + + if (!S_ISREG(st.st_mode)) { + continue; + } + + found = 0; + for (j=0;jname), dent->d_name) == 0) { + found = 1; + break; + } + } + + if (found == 1) { + continue; + } + + gotdesc = 0; + description = NULL; + + for (i=0;id_name) >= strlen(archivers[i]->extension) + 1) { + if (strcasecmp(&dent->d_name[strlen(dent->d_name) - strlen(archivers[i]->extension)], archivers[i]->extension) == 0) { + // match + bpos = 0; + for (j=0;junpack);j++) { + if (archivers[i]->unpack[j] == '*') { + j++; + if (archivers[i]->unpack[j] == 'a') { + sprintf(&buffer[bpos], "%s/%s", file_directories[current_dir]->file_subs[current_sub]->upload_path, dent->d_name); + bpos = strlen(buffer); + } else if (archivers[i]->unpack[j] == 'd') { + sprintf(&buffer[bpos], "/tmp/filecenter_temp"); + bpos = strlen(buffer); + } else if (archivers[i]->unpack[j] == '*') { + buffer[bpos++] = '*'; + buffer[bpos] = '\0'; + } + } else { + buffer[bpos++] = archivers[i]->unpack[j]; + buffer[bpos] = '\0'; + } + } + + system(buffer); + + snprintf(buffer, PATH_MAX, "/tmp/filecenter_temp/FILE_ID.DIZ"); + if (stat(buffer, &st) != 0) { + snprintf(buffer, PATH_MAX, "/tmp/filecenter_temp/file_id.diz"); + if (stat(buffer, &st) != 0) { + gotdesc = 0; + snprintf(buffer, PATH_MAX, "/tmp/filecenter_temp"); + recursive_delete(buffer); + break; + } + } + + description = (char *)malloc(st.st_size + 1); + + fptr = fopen(buffer, "rb"); + + fread(description, 1, st.st_size, fptr); + description[st.st_size] = '\0'; + fclose(fptr); + + bpos = 0; + len = strlen(description); + for (j=0;jd_name) + 30); + sprintf(filenames[fcount], "%s (unapproved)", dent->d_name); + + if (fcount == 0) { + f = (struct files **)malloc(sizeof(struct files *)); + } else { + f = (struct files **)realloc(f, sizeof(struct files *) * (fcount + 1)); + } + f[fcount] = (struct files *)malloc(sizeof(struct files)); + f[fcount]->name = (char *)malloc(strlen(file_directories[current_dir]->file_subs[current_sub]->upload_path) + strlen(dent->d_name) + 2); + sprintf(f[fcount]->name, "%s/%s", file_directories[current_dir]->file_subs[current_sub]->upload_path, dent->d_name); + f[fcount]->description = description; + f[fcount]->approved = 0; + + // add to database + snprintf(database, PATH_MAX, "%s/%s.sq3", bbspath, file_directories[current_dir]->file_subs[current_sub]->database); + + rc = sqlite3_open(database, &db); + if (rc != SQLITE_OK) { + free(f[fcount]->name); + free(f[fcount]->description); + free(filenames[fcount]); + free(f[fcount]); + if (fcount == 0) { + free(f); + free(filenames); + } else { + f = (struct files **)realloc(f, sizeof(struct files *) * fcount); + filenames = (char **)realloc(filenames, sizeof(char *) * fcount); + } + setCDKScrollItems(s, filenames, fcount, FALSE); + eraseCDKScroll(s); + drawCDKScroll(s, TRUE); + refreshCDKScreen(cdkscreen); + closedir(ind); + return FALSE; + } + + sqlite3_busy_timeout(db, 5000); + rc = sqlite3_prepare_v2(db, addfilesql, -1, &res, 0); + if (rc != SQLITE_OK) { + sqlite3_close(db); + free(f[fcount]->name); + free(f[fcount]->description); + free(filenames[fcount]); + free(f[fcount]); + if (fcount == 0) { + free(f); + free(filenames); + } else { + f = (struct files **)realloc(f, sizeof(struct files *) * fcount); + filenames = (char **)realloc(filenames, sizeof(char *) * fcount); + } + + setCDKScrollItems(s, filenames, fcount, FALSE); + eraseCDKScroll(s); + drawCDKScroll(s, TRUE); + refreshCDKScreen(cdkscreen); + closedir(ind); + return FALSE; + } + stat(f[fcount]->name, &st); + + sqlite3_bind_text(res, 1, f[fcount]->name, -1, 0); + sqlite3_bind_text(res, 2, f[fcount]->description, -1, 0); + sqlite3_bind_int(res, 3, st.st_size); + fdate = time(NULL); + sqlite3_bind_int(res, 4, fdate); + + sqlite3_step(res); + + sqlite3_finalize(res); + sqlite3_close(db); + fcount++; + + } + setCDKScrollItems(s, filenames, fcount, FALSE); + eraseCDKScroll(s); + drawCDKScroll(s, TRUE); + refreshCDKScreen(cdkscreen); + closedir(ind); + return FALSE; +} + void list_files(int dir, int sub) { CDKSCROLL *scrollList = 0; int selection; @@ -301,7 +608,7 @@ void list_files(int dir, int sub) { snprintf(title, 42, "%s", file_directories[dir]->file_subs[sub]->name); - snprintf(database, PATH_MAX, "%s/%s.sq3", configpath, file_directories[dir]->file_subs[sub]->database); + snprintf(database, PATH_MAX, "%s/%s.sq3", bbspath, file_directories[dir]->file_subs[sub]->database); // populate scroll list rc = sqlite3_open(database, &db); @@ -373,6 +680,7 @@ void list_files(int dir, int sub) { bindCDKObject (vSCROLL, scrollList, 'a', approveFile, NULL); bindCDKObject (vSCROLL, scrollList, 'd', deleteFile, NULL); + bindCDKObject (vSCROLL, scrollList, 's', scanFiles, NULL); while(1) { selection = activateCDKScroll(scrollList, 0); @@ -449,8 +757,14 @@ int main(int argc, char **argv) { exit(-1); } + snprintf(buffer, 1024, "%s/archivers.ini", configpath); + if (ini_parse(buffer, archiver_config_handler, NULL) <0) { + fprintf(stderr, "Unable to load configuration ini %s\n", buffer); + exit(-1); + } + for (i=0;ipath); + snprintf(buffer, PATH_MAX, "%s/%s", bbspath, file_directories[i]->path); if (ini_parse(buffer, file_sub_handler, file_directories[i])) { fprintf(stderr, "Unable to load %s\n", buffer); exit(-1);