54093060cb
More cleaning up construction of arrays of things. Introduce a utility function called, `split_on_space` that tokenizes a string on a space character; use it in most places where `strtok()` had been called. More use of the ptr_vector type. Introduce a utility function to get access to the pointers without consuming the vector; this is used in the files code. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
1868 lines
44 KiB
C
1868 lines
44 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sqlite3.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <libgen.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <termios.h>
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
#include <sys/wait.h>
|
|
#include "Xmodem/zmodem.h"
|
|
#include "bbs.h"
|
|
#include "lua/lua.h"
|
|
#include "lua/lualib.h"
|
|
#include "lua/lauxlib.h"
|
|
extern struct bbs_config conf;
|
|
extern int gSocket;
|
|
extern int sshBBS;
|
|
extern int mynode;
|
|
extern int bbs_stdin;
|
|
extern int bbs_stdout;
|
|
extern int bbs_stderr;
|
|
extern time_t userlaston;
|
|
extern struct user_record *gUser;
|
|
extern int telnet_bin_mode;
|
|
extern int timeoutpaused;
|
|
|
|
struct file_entry {
|
|
int fid;
|
|
int dir;
|
|
int sub;
|
|
char *filename;
|
|
char *description;
|
|
int size;
|
|
int dlcount;
|
|
time_t uploaddate;
|
|
};
|
|
|
|
struct tagged_file {
|
|
char *filename;
|
|
int dir;
|
|
int sub;
|
|
int fid;
|
|
};
|
|
|
|
struct tagged_file **tagged_files;
|
|
int tagged_count = 0;
|
|
|
|
int ttySetRaw(int fd, struct termios *prevTermios) {
|
|
struct termios t;
|
|
|
|
if (tcgetattr(fd, &t) == -1)
|
|
return -1;
|
|
|
|
if (prevTermios != NULL)
|
|
*prevTermios = t;
|
|
|
|
t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO);
|
|
t.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | INLCR | INPCK | ISTRIP | IXON | PARMRK);
|
|
t.c_oflag &= ~OPOST;
|
|
t.c_cc[VMIN] = 1;
|
|
t.c_cc[VTIME] = 0;
|
|
|
|
if (tcsetattr(fd, TCSAFLUSH, &t) == -1)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ZXmitStr(u_char *str, int len, ZModem *info) {
|
|
int i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (str[i] == 255 && !sshBBS) {
|
|
if (write(info->ofd, &str[i], 1) == 0) {
|
|
return ZmErrSys;
|
|
}
|
|
}
|
|
if (write(info->ofd, &str[i], 1) == 0) {
|
|
return ZmErrSys;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ZIFlush(ZModem *info) {
|
|
}
|
|
|
|
void ZOFlush(ZModem *info) {
|
|
}
|
|
|
|
int ZAttn(ZModem *info) {
|
|
char *ptr;
|
|
|
|
if (info->attn == NULL)
|
|
return 0;
|
|
|
|
for (ptr = info->attn; *ptr != '\0'; ++ptr) {
|
|
if (*ptr == ATTNBRK) {
|
|
|
|
} else if (*ptr == ATTNPSE) {
|
|
sleep(1);
|
|
} else {
|
|
write(info->ifd, ptr, 1);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ZFlowControl(int onoff, ZModem *info) {
|
|
}
|
|
|
|
void ZStatus(int type, int value, char *status) {
|
|
}
|
|
|
|
char *upload_path;
|
|
char upload_filename[1024];
|
|
|
|
FILE *ZOpenFile(char *name, u_long crc, ZModem *info) {
|
|
|
|
FILE *fptr;
|
|
struct stat s;
|
|
|
|
snprintf(upload_filename, 1023, "%s/%s", upload_path, basename(name));
|
|
if (stat(upload_filename, &s) == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
fptr = fopen(upload_filename, "wb");
|
|
|
|
return fptr;
|
|
}
|
|
|
|
int ZWriteFile(u_char *buffer, int len, FILE *file, ZModem *info) {
|
|
return fwrite(buffer, 1, len, file) == len ? 0 : ZmErrSys;
|
|
}
|
|
|
|
int ZCloseFile(ZModem *info) {
|
|
fclose(info->file);
|
|
return 0;
|
|
}
|
|
|
|
void ZIdleStr(u_char *buffer, int len, ZModem *info) {
|
|
}
|
|
|
|
int doIO(ZModem *zm) {
|
|
fd_set readfds;
|
|
struct timeval timeout;
|
|
u_char buffer[2048];
|
|
u_char buffer2[1024];
|
|
int len;
|
|
int pos;
|
|
int done = 0;
|
|
int i;
|
|
int j;
|
|
char iac_binary_will[] = {IAC, IAC_WILL, IAC_TRANSMIT_BINARY, '\0'};
|
|
char iac_binary_do[] = {IAC, IAC_DO, IAC_TRANSMIT_BINARY, '\0'};
|
|
char iac_binary_wont[] = {IAC, IAC_WONT, IAC_TRANSMIT_BINARY, '\0'};
|
|
char iac_binary_dont[] = {IAC, IAC_DONT, IAC_TRANSMIT_BINARY, '\0'};
|
|
|
|
while (!done) {
|
|
FD_ZERO(&readfds);
|
|
FD_SET(zm->ifd, &readfds);
|
|
timeout.tv_sec = zm->timeout;
|
|
timeout.tv_usec = 0;
|
|
i = select(zm->ifd + 1, &readfds, NULL, NULL, &timeout);
|
|
|
|
if (i == 0) {
|
|
done = ZmodemTimeout(zm);
|
|
} else if (i > 0) {
|
|
len = read(zm->ifd, buffer, 2048);
|
|
if (len == 0) {
|
|
disconnect("Socket closed");
|
|
}
|
|
|
|
pos = 0;
|
|
for (j = 0; j < len; j++) {
|
|
if (buffer[j] == 255 && !sshBBS) {
|
|
if (buffer[j + 1] == 255) {
|
|
buffer2[pos] = 255;
|
|
pos++;
|
|
j++;
|
|
} else {
|
|
// IAC command
|
|
if (buffer[j + 1] == IAC_WILL || buffer[j + 1] == IAC_WONT || buffer[j + 1] == IAC_DO || buffer[j + 1] == IAC_DONT) {
|
|
switch (buffer[j + 1]) {
|
|
case IAC_WILL:
|
|
if (buffer[j + 2] == 0) {
|
|
if (telnet_bin_mode != 1) {
|
|
telnet_bin_mode = 1;
|
|
write(gSocket, iac_binary_do, 3);
|
|
}
|
|
}
|
|
break;
|
|
case IAC_WONT:
|
|
if (buffer[j + 2] == 0) {
|
|
if (telnet_bin_mode != 0) {
|
|
telnet_bin_mode = 0;
|
|
write(gSocket, iac_binary_dont, 3);
|
|
}
|
|
}
|
|
break;
|
|
case IAC_DO:
|
|
if (buffer[j + 2] == 0) {
|
|
if (telnet_bin_mode != 1) {
|
|
telnet_bin_mode = 1;
|
|
write(gSocket, iac_binary_will, 3);
|
|
}
|
|
}
|
|
break;
|
|
case IAC_DONT:
|
|
if (buffer[j + 2] == 0) {
|
|
if (telnet_bin_mode != 0) {
|
|
telnet_bin_mode = 0;
|
|
write(gSocket, iac_binary_wont, 3);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
j += 2;
|
|
} else if (buffer[j + 1] == 250) {
|
|
j++;
|
|
do {
|
|
j++;
|
|
} while (buffer[j] != 240);
|
|
}
|
|
}
|
|
} else {
|
|
buffer2[pos] = buffer[j];
|
|
pos++;
|
|
}
|
|
}
|
|
if (pos > 0) {
|
|
done = ZmodemRcv(buffer2, pos, zm);
|
|
}
|
|
} else {
|
|
// SIG INT catch
|
|
if (errno != EINTR) {
|
|
dolog("SELECT ERROR %s", strerror(errno));
|
|
}
|
|
}
|
|
}
|
|
return done;
|
|
}
|
|
|
|
void upload_zmodem(struct user_record *user, char *upload_p) {
|
|
ZModem zm;
|
|
struct termios oldit;
|
|
struct termios oldot;
|
|
if (sshBBS) {
|
|
ttySetRaw(STDIN_FILENO, &oldit);
|
|
ttySetRaw(STDOUT_FILENO, &oldot);
|
|
}
|
|
|
|
upload_path = upload_p;
|
|
|
|
zm.attn = NULL;
|
|
zm.windowsize = 0;
|
|
zm.bufsize = 0;
|
|
|
|
if (!sshBBS) {
|
|
zm.ifd = gSocket;
|
|
zm.ofd = gSocket;
|
|
} else {
|
|
zm.ifd = STDIN_FILENO;
|
|
zm.ofd = STDOUT_FILENO;
|
|
}
|
|
zm.zrinitflags = 0;
|
|
zm.zsinitflags = 0;
|
|
|
|
zm.packetsize = 1024;
|
|
|
|
ZmodemRInit(&zm);
|
|
|
|
doIO(&zm);
|
|
if (sshBBS) {
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldit);
|
|
tcsetattr(STDOUT_FILENO, TCSANOW, &oldot);
|
|
}
|
|
}
|
|
|
|
char *get_file_id_diz(char *filename) {
|
|
char *description;
|
|
char buffer[1024];
|
|
struct stat s;
|
|
int bpos;
|
|
int i;
|
|
FILE *fptr;
|
|
int len;
|
|
int ext;
|
|
int arch;
|
|
int stout;
|
|
int stin;
|
|
int sterr;
|
|
int ret;
|
|
pid_t pid;
|
|
char **args;
|
|
char *cmd;
|
|
ext = 0;
|
|
arch = -1;
|
|
|
|
for (i = strlen(filename) - 1; i >= 0; i--) {
|
|
if (filename[i] == '.') {
|
|
ext = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ext == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < conf.archiver_count; i++) {
|
|
if (strcasecmp(&filename[ext], conf.archivers[i]->extension) == 0) {
|
|
arch = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (arch == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
snprintf(buffer, 1024, "%s/node%d", conf.bbs_path, mynode);
|
|
if (stat(buffer, &s) != 0) {
|
|
mkdir(buffer, 0755);
|
|
}
|
|
|
|
snprintf(buffer, 1024, "%s/node%d/temp", conf.bbs_path, mynode);
|
|
if (stat(buffer, &s) == 0) {
|
|
|
|
if (recursive_delete(buffer) != 0) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
mkdir(buffer, 0755);
|
|
|
|
bpos = 0;
|
|
for (i = 0; i < strlen(conf.archivers[arch]->unpack); i++) {
|
|
if (conf.archivers[arch]->unpack[i] == '*') {
|
|
i++;
|
|
if (conf.archivers[arch]->unpack[i] == 'a') {
|
|
sprintf(&buffer[bpos], "%s", filename);
|
|
bpos = strlen(buffer);
|
|
} else if (conf.archivers[arch]->unpack[i] == 'd') {
|
|
sprintf(&buffer[bpos], "%s/node%d/temp/", conf.bbs_path, mynode);
|
|
bpos = strlen(buffer);
|
|
} else if (conf.archivers[arch]->unpack[i] == '*') {
|
|
buffer[bpos++] = '*';
|
|
buffer[bpos] = '\0';
|
|
}
|
|
} else {
|
|
buffer[bpos++] = conf.archivers[arch]->unpack[i];
|
|
buffer[bpos] = '\0';
|
|
}
|
|
}
|
|
|
|
if (sshBBS) {
|
|
stout = dup(STDOUT_FILENO);
|
|
stin = dup(STDIN_FILENO);
|
|
sterr = dup(STDERR_FILENO);
|
|
|
|
dup2(bbs_stdout, STDOUT_FILENO);
|
|
dup2(bbs_stderr, STDERR_FILENO);
|
|
dup2(bbs_stdin, STDIN_FILENO);
|
|
}
|
|
args = split_on_space(buffer, NULL);
|
|
cmd = args[0];
|
|
pid = fork();
|
|
if (pid == 0) {
|
|
execvp(cmd, args);
|
|
exit(0);
|
|
} else if (pid > 0) {
|
|
waitpid(pid, &ret, 0);
|
|
} else {
|
|
ret = -1;
|
|
}
|
|
free(args);
|
|
|
|
if (sshBBS) {
|
|
|
|
dup2(stout, STDOUT_FILENO);
|
|
dup2(sterr, STDERR_FILENO);
|
|
dup2(stin, STDIN_FILENO);
|
|
|
|
close(stin);
|
|
close(stout);
|
|
close(sterr);
|
|
}
|
|
|
|
snprintf(buffer, 1024, "%s/node%d/temp/FILE_ID.DIZ", conf.bbs_path, mynode);
|
|
description = file2str(buffer);
|
|
if (description == NULL) {
|
|
snprintf(buffer, 1024, "%s/node%d/temp/file_id.diz", conf.bbs_path, mynode);
|
|
description = file2str(buffer);
|
|
if (description == NULL) {
|
|
snprintf(buffer, 1024, "%s/node%d/temp", conf.bbs_path, mynode);
|
|
recursive_delete(buffer);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
bpos = 0;
|
|
len = strlen(description);
|
|
for (i = 0; i < len; i++) {
|
|
if (description[i] == '\r') {
|
|
continue;
|
|
} else {
|
|
description[bpos++] = description[i];
|
|
}
|
|
}
|
|
description[bpos] = '\0';
|
|
|
|
snprintf(buffer, 1024, "%s/node%d/temp", conf.bbs_path, mynode);
|
|
recursive_delete(buffer);
|
|
|
|
return description;
|
|
}
|
|
|
|
int do_download(struct user_record *user, char *file) {
|
|
struct termios oldit;
|
|
struct termios oldot;
|
|
char download_command[1024];
|
|
int i;
|
|
int argc;
|
|
int last_char_space;
|
|
char **arguments;
|
|
int bpos;
|
|
int len;
|
|
char iac_binary_will[] = {IAC, IAC_WILL, IAC_TRANSMIT_BINARY, '\0'};
|
|
char iac_binary_do[] = {IAC, IAC_DO, IAC_TRANSMIT_BINARY, '\0'};
|
|
|
|
if (conf.protocols[user->defprotocol - 1]->internal_zmodem) {
|
|
if (sshBBS) {
|
|
ttySetRaw(STDIN_FILENO, &oldit);
|
|
ttySetRaw(STDOUT_FILENO, &oldot);
|
|
} else {
|
|
if (telnet_bin_mode == 0) {
|
|
write(gSocket, iac_binary_will, 3);
|
|
write(gSocket, iac_binary_do, 3);
|
|
}
|
|
}
|
|
timeoutpaused = 1;
|
|
download_zmodem(user, file);
|
|
timeoutpaused = 0;
|
|
if (sshBBS) {
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldit);
|
|
tcsetattr(STDOUT_FILENO, TCSANOW, &oldot);
|
|
}
|
|
return 1;
|
|
} else {
|
|
bpos = 0;
|
|
for (i = 0; i < strlen(conf.protocols[user->defprotocol - 1]->download); i++) {
|
|
if (conf.protocols[user->defprotocol - 1]->download[i] == '*') {
|
|
i++;
|
|
if (conf.protocols[user->defprotocol - 1]->download[i] == '*') {
|
|
download_command[bpos++] = conf.protocols[user->defprotocol - 1]->download[i];
|
|
download_command[bpos] = '\0';
|
|
continue;
|
|
} else if (conf.protocols[user->defprotocol - 1]->download[i] == 'f') {
|
|
sprintf(&download_command[bpos], "%s", file);
|
|
bpos = strlen(download_command);
|
|
|
|
continue;
|
|
} else if (conf.protocols[user->defprotocol - 1]->download[i] == 's') {
|
|
if (!sshBBS) {
|
|
sprintf(&download_command[bpos], "%d", gSocket);
|
|
bpos = strlen(download_command);
|
|
} else {
|
|
s_printf(get_string(209), conf.protocols[user->defprotocol - 1]->name);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
download_command[bpos++] = conf.protocols[user->defprotocol - 1]->download[i];
|
|
download_command[bpos] = '\0';
|
|
}
|
|
}
|
|
argc = 1;
|
|
last_char_space = 0;
|
|
for (i = 0; i < strlen(download_command); i++) {
|
|
if (download_command[i] == ' ') {
|
|
if (!last_char_space) {
|
|
argc++;
|
|
last_char_space = 1;
|
|
}
|
|
} else {
|
|
last_char_space = 0;
|
|
}
|
|
}
|
|
bpos = 1;
|
|
arguments = (char **)malloz(sizeof(char *) * (argc + 1));
|
|
len = strlen(download_command);
|
|
for (i = 0; i < len;) {
|
|
if (download_command[i] != ' ') {
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
download_command[i] = '\0';
|
|
i++;
|
|
|
|
while (download_command[i] == ' ')
|
|
i++;
|
|
|
|
arguments[bpos++] = &download_command[i];
|
|
}
|
|
arguments[bpos] = NULL;
|
|
|
|
arguments[0] = download_command;
|
|
if (!sshBBS) {
|
|
if (telnet_bin_mode == 0) {
|
|
write(gSocket, iac_binary_will, 3);
|
|
write(gSocket, iac_binary_do, 3);
|
|
}
|
|
}
|
|
runexternal(user, download_command, conf.protocols[user->defprotocol - 1]->stdio, arguments, conf.bbs_path, 1, NULL);
|
|
|
|
free(arguments);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int do_upload(struct user_record *user, char *final_path) {
|
|
char upload_path[1024];
|
|
char upload_command[1024];
|
|
char buffer3[256];
|
|
int bpos;
|
|
int i;
|
|
int argc;
|
|
int last_char_space;
|
|
char **arguments;
|
|
DIR *inb;
|
|
struct dirent *dent;
|
|
struct stat s;
|
|
int len;
|
|
char iac_binary_will[] = {IAC, IAC_WILL, IAC_TRANSMIT_BINARY, '\0'};
|
|
char iac_binary_do[] = {IAC, IAC_DO, IAC_TRANSMIT_BINARY, '\0'};
|
|
|
|
if (conf.protocols[user->defprotocol - 1]->internal_zmodem) {
|
|
if (!sshBBS) {
|
|
if (telnet_bin_mode == 0) {
|
|
write(gSocket, iac_binary_will, 3);
|
|
write(gSocket, iac_binary_do, 3);
|
|
}
|
|
}
|
|
timeoutpaused = 1;
|
|
upload_zmodem(user, final_path);
|
|
timeoutpaused = 0;
|
|
return 1;
|
|
} else {
|
|
|
|
if (conf.protocols[user->defprotocol - 1]->upload_prompt) {
|
|
s_printf(get_string(210));
|
|
s_readstring(buffer3, 256);
|
|
s_printf("\r\n");
|
|
}
|
|
bpos = 0;
|
|
for (i = 0; i < strlen(conf.protocols[user->defprotocol - 1]->upload); i++) {
|
|
if (conf.protocols[user->defprotocol - 1]->upload[i] == '*') {
|
|
i++;
|
|
if (conf.protocols[user->defprotocol - 1]->upload[i] == '*') {
|
|
upload_command[bpos++] = conf.protocols[user->defprotocol - 1]->upload[i];
|
|
upload_command[bpos] = '\0';
|
|
continue;
|
|
} else if (conf.protocols[user->defprotocol - 1]->upload[i] == 'f') {
|
|
if (conf.protocols[user->defprotocol - 1]->upload_prompt) {
|
|
sprintf(&upload_command[bpos], "%s", buffer3);
|
|
bpos = strlen(upload_command);
|
|
}
|
|
continue;
|
|
} else if (conf.protocols[user->defprotocol - 1]->upload[i] == 's') {
|
|
if (!sshBBS) {
|
|
sprintf(&upload_command[bpos], "%d", gSocket);
|
|
bpos = strlen(upload_command);
|
|
} else {
|
|
s_printf(get_string(209), conf.protocols[user->defprotocol - 1]->name);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
upload_command[bpos++] = conf.protocols[user->defprotocol - 1]->upload[i];
|
|
upload_command[bpos] = '\0';
|
|
}
|
|
}
|
|
argc = 1;
|
|
last_char_space = 0;
|
|
for (i = 0; i < strlen(upload_command); i++) {
|
|
if (upload_command[i] == ' ') {
|
|
if (!last_char_space) {
|
|
argc++;
|
|
last_char_space = 1;
|
|
}
|
|
} else {
|
|
last_char_space = 0;
|
|
}
|
|
}
|
|
bpos = 1;
|
|
arguments = (char **)malloz(sizeof(char *) * (argc + 1));
|
|
len = strlen(upload_command);
|
|
for (i = 0; i < len;) {
|
|
if (upload_command[i] != ' ') {
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
upload_command[i] = '\0';
|
|
i++;
|
|
|
|
while (upload_command[i] == ' ')
|
|
i++;
|
|
|
|
arguments[bpos++] = &upload_command[i];
|
|
}
|
|
arguments[bpos] = NULL;
|
|
|
|
arguments[0] = upload_command;
|
|
|
|
snprintf(upload_path, 1024, "%s/node%d/upload/", conf.bbs_path, mynode);
|
|
|
|
if (stat(upload_path, &s) == 0) {
|
|
recursive_delete(upload_path);
|
|
}
|
|
|
|
mkdir(upload_path, 0755);
|
|
|
|
if (!sshBBS) {
|
|
if (telnet_bin_mode == 0) {
|
|
write(gSocket, iac_binary_will, 3);
|
|
write(gSocket, iac_binary_do, 3);
|
|
}
|
|
}
|
|
runexternal(user, upload_command, conf.protocols[user->defprotocol - 1]->stdio, arguments, upload_path, 1, NULL);
|
|
|
|
free(arguments);
|
|
|
|
if (conf.protocols[user->defprotocol - 1]->upload_prompt) {
|
|
snprintf(upload_command, 1024, "%s%s", upload_path, buffer3);
|
|
if (stat(upload_command, &s) != 0) {
|
|
recursive_delete(upload_path);
|
|
return 0;
|
|
}
|
|
|
|
snprintf(upload_filename, 1024, "%s/%s", final_path, buffer3);
|
|
if (stat(upload_filename, &s) == 0) {
|
|
recursive_delete(upload_path);
|
|
s_printf(get_string(214));
|
|
return 0;
|
|
}
|
|
if (copy_file(upload_command, upload_filename) != 0) {
|
|
recursive_delete(upload_path);
|
|
return 0;
|
|
}
|
|
|
|
recursive_delete(upload_path);
|
|
return 1;
|
|
} else {
|
|
inb = opendir(upload_path);
|
|
if (!inb) {
|
|
return 0;
|
|
}
|
|
while ((dent = readdir(inb)) != NULL) {
|
|
#ifdef __sun
|
|
snprintf(upload_command, 1024, "%s%s", upload_path, dent->d_name);
|
|
stat(upload_command, &s);
|
|
if (S_ISREG(s.st_mode)) {
|
|
#else
|
|
if (dent->d_type == DT_REG) {
|
|
#endif
|
|
snprintf(upload_command, 1024, "%s%s", upload_path, dent->d_name);
|
|
snprintf(upload_filename, 1024, "%s/%s", final_path, dent->d_name);
|
|
|
|
if (stat(upload_filename, &s) == 0) {
|
|
recursive_delete(upload_path);
|
|
s_printf(get_string(214));
|
|
closedir(inb);
|
|
return 0;
|
|
}
|
|
|
|
if (copy_file(upload_command, upload_filename) != 0) {
|
|
recursive_delete(upload_path);
|
|
closedir(inb);
|
|
return 0;
|
|
}
|
|
closedir(inb);
|
|
recursive_delete(upload_path);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
closedir(inb);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
void upload(struct user_record *user) {
|
|
char buffer[331];
|
|
char buffer2[66];
|
|
char buffer3[256];
|
|
|
|
int i;
|
|
char *create_sql = "CREATE TABLE IF NOT EXISTS files ("
|
|
"Id INTEGER PRIMARY KEY,"
|
|
"filename TEXT,"
|
|
"description TEXT,"
|
|
"size INTEGER,"
|
|
"dlcount INTEGER,"
|
|
"uploaddate INTEGER,"
|
|
"approved INTEGER);";
|
|
char *sql = "INSERT INTO files (filename, description, size, dlcount, approved, uploaddate) VALUES(?, ?, ?, 0, 0, ?)";
|
|
sqlite3 *db;
|
|
sqlite3_stmt *res;
|
|
int rc;
|
|
struct stat s;
|
|
char *err_msg = NULL;
|
|
char *description;
|
|
time_t curtime;
|
|
|
|
if (!do_upload(user, conf.file_directories[user->cur_file_dir]->file_subs[user->cur_file_sub]->upload_path)) {
|
|
s_printf(get_string(211));
|
|
return;
|
|
}
|
|
|
|
description = NULL;
|
|
|
|
s_printf(get_string(198));
|
|
description = get_file_id_diz(upload_filename);
|
|
|
|
if (description == NULL) {
|
|
s_printf(get_string(199));
|
|
s_printf(get_string(200));
|
|
buffer[0] = '\0';
|
|
for (i = 0; i < 5; i++) {
|
|
s_printf("\r\n%d: ", i);
|
|
s_readstring(buffer2, 65);
|
|
if (strlen(buffer2) == 0) {
|
|
break;
|
|
}
|
|
strcat(buffer, buffer2);
|
|
strcat(buffer, "\n");
|
|
}
|
|
|
|
} else {
|
|
s_printf(get_string(201));
|
|
}
|
|
sprintf(buffer3, "%s/%s.sq3", conf.bbs_path, conf.file_directories[user->cur_file_dir]->file_subs[user->cur_file_sub]->database);
|
|
|
|
rc = sqlite3_open(buffer3, &db);
|
|
|
|
if (rc != SQLITE_OK) {
|
|
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
|
sqlite3_close(db);
|
|
exit(1);
|
|
}
|
|
sqlite3_busy_timeout(db, 5000);
|
|
rc = sqlite3_exec(db, create_sql, 0, 0, &err_msg);
|
|
if (rc != SQLITE_OK) {
|
|
dolog("SQL error: %s", err_msg);
|
|
sqlite3_free(err_msg);
|
|
sqlite3_close(db);
|
|
if (description != NULL) {
|
|
free(description);
|
|
}
|
|
return;
|
|
}
|
|
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
|
|
|
|
if (rc == SQLITE_OK) {
|
|
stat(upload_filename, &s);
|
|
|
|
sqlite3_bind_text(res, 1, upload_filename, -1, 0);
|
|
if (description == NULL) {
|
|
sqlite3_bind_text(res, 2, buffer, -1, 0);
|
|
} else {
|
|
sqlite3_bind_text(res, 2, description, -1, 0);
|
|
}
|
|
sqlite3_bind_int(res, 3, s.st_size);
|
|
curtime = time(NULL);
|
|
sqlite3_bind_int(res, 4, curtime);
|
|
} else {
|
|
dolog("Failed to execute statement: %s", sqlite3_errmsg(db));
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
if (description != NULL) {
|
|
free(description);
|
|
}
|
|
return;
|
|
}
|
|
|
|
rc = sqlite3_step(res);
|
|
|
|
if (rc != SQLITE_DONE) {
|
|
dolog("execution failed: %s", sqlite3_errmsg(db));
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
if (description != NULL) {
|
|
free(description);
|
|
}
|
|
return;
|
|
}
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
if (description != NULL) {
|
|
free(description);
|
|
}
|
|
|
|
s_printf(get_string(202));
|
|
s_printf(get_string(6));
|
|
s_getc();
|
|
}
|
|
|
|
void download_zmodem(struct user_record *user, char *filename) {
|
|
ZModem zm;
|
|
int done;
|
|
|
|
dolog("Attempting to upload %s", filename);
|
|
|
|
zm.attn = NULL;
|
|
zm.windowsize = 0;
|
|
zm.bufsize = 0;
|
|
|
|
if (!sshBBS) {
|
|
zm.ifd = gSocket;
|
|
zm.ofd = gSocket;
|
|
} else {
|
|
zm.ifd = STDIN_FILENO;
|
|
zm.ofd = STDOUT_FILENO;
|
|
}
|
|
zm.zrinitflags = 0;
|
|
zm.zsinitflags = 0;
|
|
|
|
zm.packetsize = 1024;
|
|
|
|
ZmodemTInit(&zm);
|
|
done = doIO(&zm);
|
|
if (done != ZmDone) {
|
|
return;
|
|
}
|
|
|
|
done = ZmodemTFile(filename, basename(filename), ZCBIN, 0, 0, 0, 0, 0, &zm);
|
|
|
|
switch (done) {
|
|
case 0:
|
|
break;
|
|
|
|
case ZmErrCantOpen:
|
|
dolog("cannot open file \"%s\": %s", filename, strerror(errno));
|
|
return;
|
|
|
|
case ZmFileTooLong:
|
|
dolog("filename \"%s\" too long, skipping...", filename);
|
|
return;
|
|
|
|
case ZmDone:
|
|
return;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if (!done) {
|
|
done = doIO(&zm);
|
|
}
|
|
|
|
if (done != ZmDone) {
|
|
return;
|
|
}
|
|
|
|
done = ZmodemTFinish(&zm);
|
|
|
|
if (!done) {
|
|
done = doIO(&zm);
|
|
}
|
|
}
|
|
|
|
void genurls() {
|
|
#if defined(ENABLE_WWW)
|
|
int i;
|
|
char *url;
|
|
if (conf.www_server) {
|
|
for (i = 0; i < tagged_count; i++) {
|
|
if (i % 6 == 0 && i != 0) {
|
|
// pause
|
|
s_printf(get_string(6));
|
|
s_getc();
|
|
}
|
|
|
|
url = www_create_link(tagged_files[i]->dir, tagged_files[i]->sub, tagged_files[i]->fid);
|
|
|
|
if (url != NULL) {
|
|
s_printf(get_string(255), basename(tagged_files[i]->filename));
|
|
s_printf(get_string(256), url);
|
|
free(url);
|
|
} else {
|
|
s_printf(get_string(257));
|
|
}
|
|
}
|
|
for (i = 0; i < tagged_count; i++) {
|
|
free(tagged_files[i]->filename);
|
|
free(tagged_files[i]);
|
|
}
|
|
free(tagged_files);
|
|
tagged_count = 0;
|
|
s_printf(get_string(6));
|
|
s_getc();
|
|
} else {
|
|
s_printf(get_string(258));
|
|
s_printf(get_string(6));
|
|
s_getc();
|
|
}
|
|
#else
|
|
s_printf(get_string(258));
|
|
s_printf(get_string(6));
|
|
s_getc();
|
|
#endif
|
|
}
|
|
|
|
void download(struct user_record *user) {
|
|
int i;
|
|
char *ssql = "select dlcount from files where filename like ?";
|
|
char *usql = "update files set dlcount=? where filename like ?";
|
|
char buffer[256];
|
|
int dloads;
|
|
sqlite3 *db;
|
|
sqlite3_stmt *res;
|
|
int rc;
|
|
|
|
for (i = 0; i < tagged_count; i++) {
|
|
s_printf(get_string(254), basename(tagged_files[i]->filename));
|
|
|
|
do_download(user, tagged_files[i]->filename);
|
|
|
|
sprintf(buffer, "%s/%s.sq3", conf.bbs_path, conf.file_directories[tagged_files[i]->dir]->file_subs[tagged_files[i]->sub]->database);
|
|
|
|
rc = sqlite3_open(buffer, &db);
|
|
|
|
if (rc != SQLITE_OK) {
|
|
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
|
sqlite3_close(db);
|
|
exit(1);
|
|
}
|
|
sqlite3_busy_timeout(db, 5000);
|
|
rc = sqlite3_prepare_v2(db, ssql, -1, &res, 0);
|
|
|
|
if (rc == SQLITE_OK) {
|
|
sqlite3_bind_text(res, 1, tagged_files[i]->filename, -1, 0);
|
|
} else {
|
|
dolog("Failed to execute statement: %s", sqlite3_errmsg(db));
|
|
}
|
|
|
|
rc = sqlite3_step(res);
|
|
|
|
if (rc != SQLITE_ROW) {
|
|
dolog("Downloaded a file not in database!!!!!");
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
exit(1);
|
|
}
|
|
|
|
dloads = sqlite3_column_int(res, 0);
|
|
dloads++;
|
|
sqlite3_finalize(res);
|
|
|
|
rc = sqlite3_prepare_v2(db, usql, -1, &res, 0);
|
|
|
|
if (rc == SQLITE_OK) {
|
|
sqlite3_bind_int(res, 1, dloads);
|
|
sqlite3_bind_text(res, 2, tagged_files[i]->filename, -1, 0);
|
|
} else {
|
|
dolog("Failed to execute statement: %s", sqlite3_errmsg(db));
|
|
}
|
|
|
|
rc = sqlite3_step(res);
|
|
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
}
|
|
|
|
for (i = 0; i < tagged_count; i++) {
|
|
free(tagged_files[i]->filename);
|
|
free(tagged_files[i]);
|
|
}
|
|
free(tagged_files);
|
|
tagged_count = 0;
|
|
}
|
|
|
|
void do_list_files(struct file_entry **files_e, int files_c) {
|
|
int file_size;
|
|
char file_unit;
|
|
int lines = 0;
|
|
int i;
|
|
int j;
|
|
int z;
|
|
int k;
|
|
int match;
|
|
struct ptr_vector files;
|
|
char buffer[6];
|
|
|
|
s_printf("\r\n");
|
|
|
|
init_ptr_vector(&files);
|
|
for (i = 0; i < files_c; i++) {
|
|
file_size = files_e[i]->size;
|
|
if (file_size > 1024 * 1024 * 1024) {
|
|
file_size = file_size / 1024 / 1024 / 1024;
|
|
file_unit = 'G';
|
|
} else if (file_size > 1024 * 1024) {
|
|
file_size = file_size / 1024 / 1024;
|
|
file_unit = 'M';
|
|
} else if (file_size > 1024) {
|
|
file_size = file_size / 1024;
|
|
file_unit = 'K';
|
|
} else {
|
|
file_unit = 'b';
|
|
}
|
|
if (files_e[i]->uploaddate > userlaston) {
|
|
s_printf(get_string(231), i, files_e[i]->dlcount, file_size, file_unit, basename(files_e[i]->filename));
|
|
} else {
|
|
s_printf(get_string(69), i, files_e[i]->dlcount, file_size, file_unit, basename(files_e[i]->filename));
|
|
}
|
|
lines += 3;
|
|
for (j = 0; j < strlen(files_e[i]->description); j++) {
|
|
if (files_e[i]->description[j] == '\n') {
|
|
s_printf("\r\n");
|
|
lines++;
|
|
if (lines >= 18) {
|
|
lines = 0;
|
|
while (1) {
|
|
s_printf(get_string(70));
|
|
s_readstring(buffer, 5);
|
|
if (strlen(buffer) == 0) {
|
|
s_printf("\r\n");
|
|
break;
|
|
} else if (tolower(buffer[0]) == 'q') {
|
|
for (z = 0; z < files_c; z++) {
|
|
free(files_e[z]->filename);
|
|
free(files_e[z]->description);
|
|
free(files_e[z]);
|
|
}
|
|
free(files_e);
|
|
s_printf("\r\n");
|
|
return;
|
|
} else {
|
|
z = atoi(buffer);
|
|
if (z >= 0 && z < files_c) {
|
|
if (conf.file_directories[files_e[z]->dir]->file_subs[files_e[z]->sub]->download_sec_level <= gUser->sec_level) {
|
|
match = 0;
|
|
for (k = 0; k < tagged_count; k++) {
|
|
if (strcmp(tagged_files[k]->filename, files_e[z]->filename) == 0) {
|
|
match = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (match == 0) {
|
|
struct tagged_file *file = (struct tagged_file *)malloz(sizeof(struct tagged_file));
|
|
file->filename = strdup(files_e[z]->filename);
|
|
file->dir = files_e[z]->dir;
|
|
file->sub = files_e[z]->sub;
|
|
file->fid = files_e[z]->fid;
|
|
ptr_vector_append(&files, file);
|
|
tagged_count++;
|
|
tagged_files = (struct tagged_file **)ptr_vector_ptrs(&files);
|
|
s_printf(get_string(71), basename(files_e[z]->filename));
|
|
} else {
|
|
s_printf(get_string(72));
|
|
}
|
|
} else {
|
|
s_printf(get_string(73));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (strlen(&(files_e[i]->description[j])) > 1) {
|
|
s_printf(get_string(74));
|
|
}
|
|
} else {
|
|
s_putchar(files_e[i]->description[j]);
|
|
}
|
|
}
|
|
if (lines >= 18) {
|
|
lines = 0;
|
|
while (1) {
|
|
s_printf(get_string(70));
|
|
s_readstring(buffer, 5);
|
|
if (strlen(buffer) == 0) {
|
|
s_printf("\r\n");
|
|
break;
|
|
} else if (tolower(buffer[0]) == 'q') {
|
|
for (z = 0; z < files_c; z++) {
|
|
free(files_e[z]->filename);
|
|
free(files_e[z]->description);
|
|
free(files_e[z]);
|
|
}
|
|
free(files_e);
|
|
s_printf("\r\n");
|
|
return;
|
|
} else {
|
|
z = atoi(buffer);
|
|
if (z >= 0 && z < files_c) {
|
|
if (conf.file_directories[files_e[z]->dir]->file_subs[files_e[z]->sub]->download_sec_level <= gUser->sec_level) {
|
|
match = 0;
|
|
for (k = 0; k < tagged_count; k++) {
|
|
if (strcmp(tagged_files[k]->filename, files_e[z]->filename) == 0) {
|
|
match = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (match == 0) {
|
|
struct tagged_file *file = (struct tagged_file *)malloz(sizeof(struct tagged_file));
|
|
file->filename = strdup(files_e[z]->filename);
|
|
file->dir = files_e[z]->dir;
|
|
file->sub = files_e[z]->sub;
|
|
file->fid = files_e[z]->fid;
|
|
ptr_vector_append(&files, file);
|
|
tagged_count++;
|
|
tagged_files = (struct tagged_file **)ptr_vector_ptrs(&files);
|
|
s_printf(get_string(71), basename(files_e[z]->filename));
|
|
} else {
|
|
s_printf(get_string(72));
|
|
}
|
|
} else {
|
|
s_printf(get_string(73));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while (1) {
|
|
s_printf(get_string(75));
|
|
s_readstring(buffer, 5);
|
|
if (strlen(buffer) == 0) {
|
|
for (z = 0; z < files_c; z++) {
|
|
free(files_e[z]->filename);
|
|
free(files_e[z]->description);
|
|
free(files_e[z]);
|
|
}
|
|
free(files_e);
|
|
s_printf("\r\n");
|
|
return;
|
|
} else {
|
|
z = atoi(buffer);
|
|
if (z >= 0 && z < files_c) {
|
|
if (conf.file_directories[files_e[z]->dir]->file_subs[files_e[z]->sub]->download_sec_level <= gUser->sec_level) {
|
|
match = 0;
|
|
for (k = 0; k < tagged_count; k++) {
|
|
if (strcmp(tagged_files[k]->filename, files_e[z]->filename) == 0) {
|
|
match = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (match == 0) {
|
|
struct tagged_file *file = (struct tagged_file *)malloz(sizeof(struct tagged_file));
|
|
file->filename = strdup(files_e[z]->filename);
|
|
file->dir = files_e[z]->dir;
|
|
file->sub = files_e[z]->sub;
|
|
file->fid = files_e[z]->fid;
|
|
ptr_vector_append(&files, file);
|
|
tagged_count++;
|
|
tagged_files = (struct tagged_file **)ptr_vector_ptrs(&files);
|
|
s_printf(get_string(71), basename(files_e[z]->filename));
|
|
} else {
|
|
s_printf(get_string(72));
|
|
}
|
|
} else {
|
|
s_printf(get_string(73));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void file_search() {
|
|
char ch;
|
|
int all = 0;
|
|
int stype = 0;
|
|
char buffer[PATH_MAX];
|
|
char sqlbuffer[1024];
|
|
char **searchterms;
|
|
size_t searchterm_count = 0;
|
|
char *ptr;
|
|
int i;
|
|
int j;
|
|
int search_dir;
|
|
int search_sub;
|
|
sqlite3 *db;
|
|
sqlite3_stmt *res;
|
|
int rc;
|
|
int files_c;
|
|
struct file_entry **files_e;
|
|
struct ptr_vector files;
|
|
|
|
s_printf(get_string(236));
|
|
ch = s_getc();
|
|
|
|
switch (tolower(ch)) {
|
|
case 'd':
|
|
stype = 1;
|
|
break;
|
|
case 'b':
|
|
stype = 2;
|
|
break;
|
|
}
|
|
|
|
s_printf(get_string(237));
|
|
|
|
ch = s_getc();
|
|
if (tolower(ch) == 'a') {
|
|
all = 1;
|
|
}
|
|
|
|
s_printf(get_string(239));
|
|
|
|
s_readstring(buffer, 128);
|
|
|
|
if (strlen(buffer) == 0) {
|
|
s_printf(get_string(238));
|
|
return;
|
|
}
|
|
searchterms = split_on_space(buffer, &searchterm_count);
|
|
for (size_t i = 0; i < searchterm_count; ++i) {
|
|
searchterms[i] = str3dup("%%", searchterms[i], "%%");
|
|
}
|
|
if (stype == 0) {
|
|
snprintf(sqlbuffer, 1024, "select id, filename, description, size, dlcount, uploaddate from files where approved=1 AND (filename LIKE ?");
|
|
for (i = 1; i < searchterm_count; i++) {
|
|
strncat(sqlbuffer, " OR filename LIKE ?", 1024);
|
|
}
|
|
strncat(sqlbuffer, ")", 1024);
|
|
}
|
|
if (stype == 1) {
|
|
snprintf(sqlbuffer, 1024, "select id, filename, description, size, dlcount, uploaddate from files where approved=1 AND (description LIKE ?");
|
|
for (i = 1; i < searchterm_count; i++) {
|
|
strncat(sqlbuffer, " OR description LIKE ?", 1024);
|
|
}
|
|
strncat(sqlbuffer, ")", 1024);
|
|
}
|
|
if (stype == 2) {
|
|
snprintf(sqlbuffer, 1024, "select id, filename, description, size, dlcount, uploaddate from files where approved=1 AND (filename LIKE ?");
|
|
for (i = 1; i < searchterm_count; i++) {
|
|
strncat(sqlbuffer, " OR filename LIKE ?", 1024);
|
|
}
|
|
strncat(sqlbuffer, " OR description LIKE ?", 1024);
|
|
for (i = 1; i < searchterm_count; i++) {
|
|
strncat(sqlbuffer, " OR description LIKE ?", 1024);
|
|
}
|
|
strncat(sqlbuffer, ")", 1024);
|
|
}
|
|
|
|
if (!all) {
|
|
files_c = 0;
|
|
snprintf(buffer, PATH_MAX, "%s/%s.sq3", conf.bbs_path, conf.file_directories[gUser->cur_file_dir]->file_subs[gUser->cur_file_sub]->database);
|
|
|
|
rc = sqlite3_open(buffer, &db);
|
|
if (rc != SQLITE_OK) {
|
|
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
|
sqlite3_close(db);
|
|
|
|
exit(1);
|
|
}
|
|
sqlite3_busy_timeout(db, 5000);
|
|
rc = sqlite3_prepare_v2(db, sqlbuffer, -1, &res, 0);
|
|
|
|
if (rc != SQLITE_OK) {
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
for (i = 0; i < searchterm_count; i++) {
|
|
free(searchterms[i]);
|
|
}
|
|
free(searchterms);
|
|
return;
|
|
}
|
|
if (stype == 2) {
|
|
for (j = 0; j < 2; j++) {
|
|
for (i = 0; i < searchterm_count; i++) {
|
|
sqlite3_bind_text(res, j * searchterm_count + i + 1, searchterms[i], -1, 0);
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0; i < searchterm_count; i++) {
|
|
sqlite3_bind_text(res, i + 1, searchterms[i], -1, 0);
|
|
}
|
|
}
|
|
|
|
init_ptr_vector(&files);
|
|
while (sqlite3_step(res) == SQLITE_ROW) {
|
|
struct file_entry *file = (struct file_entry *)malloz(sizeof(struct file_entry));
|
|
file->fid = sqlite3_column_int(res, 0);
|
|
file->filename = strdup((char *)sqlite3_column_text(res, 1));
|
|
file->description = strdup((char *)sqlite3_column_text(res, 2));
|
|
file->size = sqlite3_column_int(res, 3);
|
|
file->dlcount = sqlite3_column_int(res, 4);
|
|
file->uploaddate = sqlite3_column_int(res, 5);
|
|
file->dir = gUser->cur_file_dir;
|
|
file->sub = gUser->cur_file_sub;
|
|
ptr_vector_append(&files, file);
|
|
}
|
|
files_c = ptr_vector_len(&files);
|
|
files_e = (struct file_entry **)consume_ptr_vector(&files);
|
|
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
|
|
if (files_c != 0) {
|
|
do_list_files(files_e, files_c);
|
|
}
|
|
} else {
|
|
files_c = 0;
|
|
for (search_dir = 0; search_dir < conf.file_directory_count; search_dir++) {
|
|
if (conf.file_directories[search_dir]->sec_level > gUser->sec_level) {
|
|
continue;
|
|
}
|
|
for (search_sub = 0; search_sub < conf.file_directories[search_dir]->file_sub_count; search_sub++) {
|
|
if (conf.file_directories[search_dir]->file_subs[search_sub]->download_sec_level > gUser->sec_level) {
|
|
continue;
|
|
}
|
|
snprintf(buffer, PATH_MAX, "%s/%s.sq3", conf.bbs_path, conf.file_directories[search_dir]->file_subs[search_sub]->database);
|
|
|
|
rc = sqlite3_open(buffer, &db);
|
|
if (rc != SQLITE_OK) {
|
|
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
|
sqlite3_close(db);
|
|
exit(1);
|
|
}
|
|
sqlite3_busy_timeout(db, 5000);
|
|
rc = sqlite3_prepare_v2(db, sqlbuffer, -1, &res, 0);
|
|
|
|
if (rc != SQLITE_OK) {
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
continue;
|
|
}
|
|
if (stype == 2) {
|
|
for (j = 0; j < 2; j++) {
|
|
for (i = 0; i < searchterm_count; i++) {
|
|
sqlite3_bind_text(res, j * searchterm_count + i + 1, searchterms[i], -1, 0);
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0; i < searchterm_count; i++) {
|
|
sqlite3_bind_text(res, i + 1, searchterms[i], -1, 0);
|
|
}
|
|
}
|
|
|
|
init_ptr_vector(&files);
|
|
while (sqlite3_step(res) == SQLITE_ROW) {
|
|
struct file_entry *file = (struct file_entry *)malloz(sizeof(struct file_entry));
|
|
file->fid = sqlite3_column_int(res, 0);
|
|
file->filename = strdup((char *)sqlite3_column_text(res, 1));
|
|
file->description = strdup((char *)sqlite3_column_text(res, 2));
|
|
file->size = sqlite3_column_int(res, 3);
|
|
file->dlcount = sqlite3_column_int(res, 4);
|
|
file->uploaddate = sqlite3_column_int(res, 5);
|
|
file->dir = gUser->cur_file_dir;
|
|
file->sub = gUser->cur_file_sub;
|
|
ptr_vector_append(&files, file);
|
|
}
|
|
files_c = ptr_vector_len(&files);
|
|
files_e = (struct file_entry **)consume_ptr_vector(&files);
|
|
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
}
|
|
}
|
|
|
|
if (files_c != 0) {
|
|
do_list_files(files_e, files_c);
|
|
}
|
|
}
|
|
for (i = 0; i < searchterm_count; i++) {
|
|
free(searchterms[i]);
|
|
}
|
|
free(searchterms);
|
|
}
|
|
|
|
void list_files(struct user_record *user) {
|
|
char *dsql = "select id, filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY uploaddate DESC";
|
|
char *fsql = "select id, filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY filename";
|
|
char *psql = "select id, filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY dlcount DESC";
|
|
char *nsql = "select id, filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY uploaddate DESC WHERE uploaddate > ?";
|
|
char *sql;
|
|
char buffer[PATH_MAX];
|
|
sqlite3 *db;
|
|
sqlite3_stmt *res;
|
|
int rc;
|
|
int files_c;
|
|
|
|
char ch;
|
|
struct file_entry **files_e;
|
|
struct ptr_vector files;
|
|
|
|
s_printf(get_string(233));
|
|
ch = s_getc();
|
|
|
|
switch (tolower(ch)) {
|
|
case 'u':
|
|
sql = dsql;
|
|
break;
|
|
case 'p':
|
|
sql = psql;
|
|
break;
|
|
case 'n':
|
|
sql = nsql;
|
|
break;
|
|
default:
|
|
sql = fsql;
|
|
break;
|
|
}
|
|
s_printf("\r\n");
|
|
snprintf(buffer, PATH_MAX, "%s/%s.sq3", conf.bbs_path, conf.file_directories[user->cur_file_dir]->file_subs[user->cur_file_sub]->database);
|
|
|
|
rc = sqlite3_open(buffer, &db);
|
|
if (rc != SQLITE_OK) {
|
|
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
|
sqlite3_close(db);
|
|
|
|
exit(1);
|
|
}
|
|
sqlite3_busy_timeout(db, 5000);
|
|
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
|
|
if (rc != SQLITE_OK) {
|
|
sqlite3_close(db);
|
|
s_printf(get_string(68));
|
|
return;
|
|
}
|
|
if (sql == nsql) {
|
|
sqlite3_bind_int(res, 1, userlaston);
|
|
}
|
|
|
|
init_ptr_vector(&files);
|
|
while (sqlite3_step(res) == SQLITE_ROW) {
|
|
struct file_entry *file = (struct file_entry *)malloz(sizeof(struct file_entry));
|
|
file->fid = sqlite3_column_int(res, 0);
|
|
file->filename = strdup((char *)sqlite3_column_text(res, 1));
|
|
file->description = strdup((char *)sqlite3_column_text(res, 2));
|
|
file->size = sqlite3_column_int(res, 3);
|
|
file->dlcount = sqlite3_column_int(res, 4);
|
|
file->uploaddate = sqlite3_column_int(res, 5);
|
|
file->dir = user->cur_file_dir;
|
|
file->sub = user->cur_file_sub;
|
|
ptr_vector_append(&files, file);
|
|
}
|
|
files_c = ptr_vector_len(&files);
|
|
files_e = (struct file_entry **)consume_ptr_vector(&files);
|
|
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
|
|
if (files_c == 0) {
|
|
s_printf(get_string(68));
|
|
return;
|
|
}
|
|
|
|
do_list_files(files_e, files_c);
|
|
}
|
|
|
|
struct subdir_tmp_t {
|
|
struct file_sub *sub;
|
|
int index;
|
|
};
|
|
|
|
void choose_subdir() {
|
|
int i;
|
|
int list_tmp = 0;
|
|
struct subdir_tmp_t **sub_tmp;
|
|
int redraw = 1;
|
|
int start = 0;
|
|
int selected = 0;
|
|
char c;
|
|
struct ptr_vector subs;
|
|
|
|
init_ptr_vector(&subs);
|
|
for (i = 0; i < conf.file_directories[gUser->cur_file_dir]->file_sub_count; i++) {
|
|
if (conf.file_directories[gUser->cur_file_dir]->file_subs[i]->download_sec_level <= gUser->sec_level) {
|
|
struct subdir_tmp_t *sub = (struct subdir_tmp_t *)malloz(sizeof(struct subdir_tmp_t));
|
|
sub->sub = conf.file_directories[gUser->cur_file_dir]->file_subs[i];
|
|
sub->index = i;
|
|
ptr_vector_append(&subs, sub);
|
|
}
|
|
}
|
|
list_tmp = ptr_vector_len(&subs);
|
|
sub_tmp = (struct subdir_tmp_t **)consume_ptr_vector(&subs);
|
|
|
|
while (1) {
|
|
if (redraw) {
|
|
s_printf("\e[2J\e[1;1H");
|
|
s_printf(get_string(252), conf.file_directories[gUser->cur_file_dir]->name);
|
|
s_printf(get_string(248));
|
|
for (i = start; i < start + 22 && i < list_tmp; i++) {
|
|
if (i == selected) {
|
|
s_printf(get_string(249), i - start + 2, sub_tmp[i]->index, sub_tmp[i]->sub->name);
|
|
} else {
|
|
s_printf(get_string(250), i - start + 2, sub_tmp[i]->index, sub_tmp[i]->sub->name);
|
|
}
|
|
}
|
|
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 >= list_tmp) {
|
|
start = list_tmp - 22;
|
|
}
|
|
redraw = 1;
|
|
}
|
|
selected++;
|
|
if (selected >= list_tmp) {
|
|
selected = list_tmp - 1;
|
|
} else {
|
|
if (!redraw) {
|
|
s_printf(get_string(250), selected - start + 1, sub_tmp[selected - 1]->index, sub_tmp[selected - 1]->sub->name);
|
|
s_printf(get_string(249), selected - start + 2, sub_tmp[selected]->index, sub_tmp[selected]->sub->name);
|
|
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 {
|
|
if (!redraw) {
|
|
s_printf(get_string(249), selected - start + 2, sub_tmp[selected]->index, sub_tmp[selected]->sub->name);
|
|
s_printf(get_string(250), selected - start + 3, sub_tmp[selected + 1]->index, sub_tmp[selected + 1]->sub->name);
|
|
s_printf("\e[%d;5H", selected - start + 2);
|
|
}
|
|
}
|
|
} else if (c == 75) {
|
|
// END KEY
|
|
selected = list_tmp - 1;
|
|
start = list_tmp - 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 >= list_tmp) {
|
|
selected = list_tmp - 1;
|
|
}
|
|
start = selected;
|
|
redraw = 1;
|
|
}
|
|
}
|
|
} else if (c == 13) {
|
|
gUser->cur_file_sub = sub_tmp[selected]->index;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < list_tmp; i++) {
|
|
free(sub_tmp[i]);
|
|
}
|
|
free(sub_tmp);
|
|
}
|
|
|
|
struct dir_tmp_t {
|
|
struct file_directory *dir;
|
|
int index;
|
|
};
|
|
|
|
void choose_directory() {
|
|
int i;
|
|
int list_tmp = 0;
|
|
struct dir_tmp_t **dir_tmp;
|
|
int redraw = 1;
|
|
int start = 0;
|
|
int selected = 0;
|
|
char c;
|
|
struct ptr_vector dirs;
|
|
|
|
init_ptr_vector(&dirs);
|
|
for (i = 0; i < conf.file_directory_count; i++) {
|
|
if (conf.file_directories[i]->sec_level <= gUser->sec_level) {
|
|
struct dir_tmp_t *dir = (struct dir_tmp_t *)malloz(sizeof(struct dir_tmp_t));
|
|
dir->dir = conf.file_directories[i];
|
|
dir->index = i;
|
|
ptr_vector_append(&dirs, dir);
|
|
}
|
|
}
|
|
list_tmp = ptr_vector_len(&dirs);
|
|
dir_tmp = (struct dir_tmp_t **)consume_ptr_vector(&dirs);
|
|
|
|
while (1) {
|
|
if (redraw) {
|
|
s_printf("\e[2J\e[1;1H");
|
|
s_printf(get_string(253));
|
|
s_printf(get_string(248));
|
|
for (i = start; i < start + 22 && i < list_tmp; i++) {
|
|
if (i == selected) {
|
|
s_printf(get_string(249), i - start + 2, dir_tmp[i]->index, dir_tmp[i]->dir->name);
|
|
} else {
|
|
s_printf(get_string(250), i - start + 2, dir_tmp[i]->index, dir_tmp[i]->dir->name);
|
|
}
|
|
}
|
|
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 >= list_tmp) {
|
|
start = list_tmp - 22;
|
|
}
|
|
redraw = 1;
|
|
}
|
|
selected++;
|
|
if (selected >= list_tmp) {
|
|
selected = list_tmp - 1;
|
|
} else {
|
|
if (!redraw) {
|
|
s_printf(get_string(250), selected - start + 1, dir_tmp[selected - 1]->index, dir_tmp[selected - 1]->dir->name);
|
|
s_printf(get_string(249), selected - start + 2, dir_tmp[selected]->index, dir_tmp[selected]->dir->name);
|
|
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 {
|
|
if (!redraw) {
|
|
s_printf(get_string(249), selected - start + 2, dir_tmp[selected]->index, dir_tmp[selected]->dir->name);
|
|
s_printf(get_string(250), selected - start + 3, dir_tmp[selected + 1]->index, dir_tmp[selected + 1]->dir->name);
|
|
s_printf("\e[%d;5H", selected - start + 2);
|
|
}
|
|
}
|
|
} else if (c == 75) {
|
|
// END KEY
|
|
selected = list_tmp - 1;
|
|
start = list_tmp - 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 >= list_tmp) {
|
|
selected = list_tmp - 1;
|
|
}
|
|
start = selected;
|
|
redraw = 1;
|
|
}
|
|
}
|
|
} else if (c == 13) {
|
|
gUser->cur_file_dir = dir_tmp[selected]->index;
|
|
gUser->cur_file_sub = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < list_tmp; i++) {
|
|
free(dir_tmp[i]);
|
|
}
|
|
free(dir_tmp);
|
|
}
|
|
|
|
void clear_tagged_files() {
|
|
int i;
|
|
// Clear tagged files
|
|
if (tagged_count > 0) {
|
|
for (i = 0; i < tagged_count; i++) {
|
|
free(tagged_files[i]->filename);
|
|
free(tagged_files[i]);
|
|
}
|
|
free(tagged_files);
|
|
tagged_count = 0;
|
|
}
|
|
}
|
|
|
|
void next_file_dir(struct user_record *user) {
|
|
int i;
|
|
for (i = user->cur_file_dir; i < conf.file_directory_count; i++) {
|
|
if (i + 1 == conf.file_directory_count) {
|
|
i = -1;
|
|
}
|
|
if (conf.file_directories[i + 1]->sec_level <= user->sec_level) {
|
|
user->cur_file_dir = i + 1;
|
|
user->cur_file_sub = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void prev_file_dir(struct user_record *user) {
|
|
int i;
|
|
for (i = user->cur_file_dir; i >= 0; i--) {
|
|
if (i - 1 == -1) {
|
|
i = conf.file_directory_count;
|
|
}
|
|
if (conf.file_directories[i - 1]->sec_level <= user->sec_level) {
|
|
user->cur_file_dir = i - 1;
|
|
user->cur_file_sub = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void next_file_sub(struct user_record *user) {
|
|
int i;
|
|
i = user->cur_file_sub;
|
|
if (i + 1 == conf.file_directories[user->cur_file_dir]->file_sub_count) {
|
|
i = -1;
|
|
}
|
|
user->cur_file_sub = i + 1;
|
|
}
|
|
|
|
void prev_file_sub(struct user_record *user) {
|
|
int i;
|
|
i = user->cur_file_sub;
|
|
if (i - 1 == -1) {
|
|
i = conf.file_directories[user->cur_file_dir]->file_sub_count;
|
|
}
|
|
user->cur_file_sub = i - 1;
|
|
}
|
|
|
|
void file_scan() {
|
|
char c;
|
|
int i;
|
|
int j;
|
|
char buffer[PATH_MAX];
|
|
char sql[] = "SELECT COUNT(*) FROM files WHERE uploaddate > ? AND approved=1";
|
|
int rc;
|
|
sqlite3 *db;
|
|
sqlite3_stmt *res;
|
|
int new_files;
|
|
int lines = 0;
|
|
|
|
s_printf(get_string(232));
|
|
c = s_getc();
|
|
|
|
if (tolower(c) == 'y') {
|
|
for (i = 0; i < conf.file_directory_count; i++) {
|
|
if (conf.file_directories[i]->sec_level > gUser->sec_level) {
|
|
continue;
|
|
}
|
|
s_printf(get_string(140), i, conf.file_directories[i]->name);
|
|
lines += 2;
|
|
if (lines == 22) {
|
|
s_printf(get_string(6));
|
|
s_getc();
|
|
lines = 0;
|
|
}
|
|
for (j = 0; j < conf.file_directories[i]->file_sub_count; j++) {
|
|
if (conf.file_directories[i]->file_subs[j]->download_sec_level > gUser->sec_level) {
|
|
continue;
|
|
}
|
|
snprintf(buffer, PATH_MAX, "%s/%s.sq3", conf.bbs_path, conf.file_directories[i]->file_subs[j]->database);
|
|
rc = sqlite3_open(buffer, &db);
|
|
if (rc != SQLITE_OK) {
|
|
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
|
sqlite3_close(db);
|
|
|
|
exit(1);
|
|
}
|
|
sqlite3_busy_timeout(db, 5000);
|
|
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
|
|
|
|
if (rc != SQLITE_OK) {
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
continue;
|
|
}
|
|
sqlite3_bind_int(res, 1, userlaston);
|
|
|
|
if (sqlite3_step(res) != SQLITE_ERROR) {
|
|
new_files = sqlite3_column_int(res, 0);
|
|
if (new_files > 0) {
|
|
s_printf(get_string(141), j, conf.file_directories[i]->file_subs[j]->name, new_files);
|
|
lines++;
|
|
}
|
|
}
|
|
sqlite3_finalize(res);
|
|
sqlite3_close(db);
|
|
|
|
if (lines == 22) {
|
|
s_printf(get_string(6));
|
|
s_getc();
|
|
lines = 0;
|
|
}
|
|
}
|
|
}
|
|
s_printf(get_string(6));
|
|
s_getc();
|
|
}
|
|
}
|