first attempt at www downlods WIP
This commit is contained in:
@@ -34,7 +34,7 @@ $(CDK):
|
||||
cd ../deps/cdk-5.0-20161210/ && export CPPFLAGS=-I/usr/local/include && ./configure --with-ncurses
|
||||
cd ../deps/cdk-5.0-20161210/ && $(MAKE)
|
||||
|
||||
OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o hashmap/hashmap.o menus.o
|
||||
OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o www_files.o hashmap/hashmap.o menus.o
|
||||
%.o: %.c $(DEPS)
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
|
@@ -34,7 +34,7 @@ $(CDK):
|
||||
cd ../deps/cdk-5.0-20161210/ && ./configure
|
||||
cd ../deps/cdk-5.0-20161210/ && $(MAKE)
|
||||
|
||||
OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o bluewave.o hashmap/hashmap.o menus.o
|
||||
OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o www_files.o bluewave.o hashmap/hashmap.o menus.o
|
||||
%.o: %.c $(DEPS)
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
|
@@ -34,7 +34,7 @@ $(CDK):
|
||||
cd ../deps/cdk-5.0-20161210/ && export CPPFLAGS=-I/usr/pkg/include && ./configure --with-ncurses
|
||||
cd ../deps/cdk-5.0-20161210/ && $(MAKE)
|
||||
|
||||
OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o hashmap/hashmap.o menus.o
|
||||
OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o www_files.o hashmap/hashmap.o menus.o
|
||||
%.o: %.c $(DEPS)
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
|
@@ -34,7 +34,7 @@ $(CDK):
|
||||
cd ../deps/cdk-5.0-20161210/ && export CPPFLAGS=-I/usr/pkg/include && ./configure --with-ncurses
|
||||
cd ../deps/cdk-5.0-20161210/ && $(MAKE)
|
||||
|
||||
OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o hashmap/hashmap.o menus.o
|
||||
OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o www_files.o hashmap/hashmap.o menus.o
|
||||
%.o: %.c $(DEPS)
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
|
@@ -34,7 +34,7 @@ $(CDK):
|
||||
cd ../deps/cdk-5.0-20161210/ && ./configure
|
||||
cd ../deps/cdk-5.0-20161210/ && $(MAKE)
|
||||
|
||||
OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o bluewave.o hashmap/hashmap.o menus.o
|
||||
OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o www_files.o bluewave.o hashmap/hashmap.o menus.o
|
||||
%.o: %.c $(DEPS)
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
|
@@ -34,7 +34,7 @@ $(CDK):
|
||||
cd ../deps/cdk-5.0-20161210/ && ./configure
|
||||
cd ../deps/cdk-5.0-20161210/ && $(MAKE)
|
||||
|
||||
OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o bluewave.o hashmap/hashmap.o menus.o os/sunos.o
|
||||
OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o bluewave.o www_files.o hashmap/hashmap.o menus.o os/sunos.o
|
||||
%.o: %.c $(DEPS)
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
|
@@ -895,6 +895,9 @@ tryagain:
|
||||
unlink(buffer);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_WWW)
|
||||
www_expire_old_links();
|
||||
#endif
|
||||
// do post-login
|
||||
dolog("%s logged in, on node %d", user->loginname, mynode);
|
||||
broadcast("%s logged in, on node %d", user->loginname, mynode);
|
||||
|
@@ -323,6 +323,7 @@ extern void next_file_sub(struct user_record *user);
|
||||
extern void prev_file_sub(struct user_record *user);
|
||||
extern void file_scan();
|
||||
extern void file_search();
|
||||
extern void genurls();
|
||||
|
||||
extern void lua_push_cfunctions(lua_State *L);
|
||||
extern void do_lua_script(char *script);
|
||||
@@ -350,6 +351,8 @@ extern char *www_msgs_messageview(struct user_record *user, int conference, int
|
||||
extern int www_send_msg(struct user_record *user, char *to, char *subj, int conference, int area, char *replyid, char *body);
|
||||
extern char *www_new_msg(struct user_record *user, int conference, int area);
|
||||
extern char *www_last10();
|
||||
extern void www_expire_old_links();
|
||||
extern char *www_create_link(int dir, int sub, int fid);
|
||||
#endif
|
||||
extern int menu_system(char *menufile);
|
||||
#endif
|
||||
|
45
src/files.c
45
src/files.c
@@ -798,6 +798,42 @@ void download_zmodem(struct user_record *user, char *filename) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void genurls() {
|
||||
#if defined(ENABLE_WWW)
|
||||
int i;
|
||||
char *url;
|
||||
for (i=0;i<tagged_count;i++) {
|
||||
if (i % 6) {
|
||||
// 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;
|
||||
#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 ?";
|
||||
@@ -810,6 +846,7 @@ void download(struct user_record *user) {
|
||||
|
||||
|
||||
for (i=0;i<tagged_count;i++) {
|
||||
s_printf(get_string(254), basename(tagged_files[i]->filename));
|
||||
|
||||
do_download(user, tagged_files[i]->filename);
|
||||
|
||||
@@ -1324,15 +1361,15 @@ void list_files(struct user_record *user) {
|
||||
}
|
||||
sqlite3_busy_timeout(db, 5000);
|
||||
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
|
||||
if (sql == nsql) {
|
||||
sqlite3_bind_int(res, 1, userlaston);
|
||||
}
|
||||
if (rc != SQLITE_OK) {
|
||||
sqlite3_finalize(res);
|
||||
sqlite3_close(db);
|
||||
s_printf(get_string(68));
|
||||
return;
|
||||
}
|
||||
if (sql == nsql) {
|
||||
sqlite3_bind_int(res, 1, userlaston);
|
||||
}
|
||||
|
||||
|
||||
|
||||
files_c = 0;
|
||||
|
@@ -54,6 +54,7 @@
|
||||
#define MENU_FILESEARCH 44
|
||||
#define MENU_DISPTXTFILE 45
|
||||
#define MENU_DISPTXTFILEPAUSE 46
|
||||
#define MENU_GENWWWURLS 47
|
||||
|
||||
extern struct bbs_config conf;
|
||||
extern struct user_record *gUser;
|
||||
@@ -212,7 +213,9 @@ int menu_system(char *menufile) {
|
||||
menu[menu_items-1]->command = MENU_DISPTXTFILE;
|
||||
} else if (strncasecmp(&buffer[8], "DISPLAYTXTPAUSE", 15) == 0) {
|
||||
menu[menu_items-1]->command = MENU_DISPTXTFILEPAUSE;
|
||||
}
|
||||
} else if (strncasecmp(&buffer[8], "GENWWWURLS", 10) == 0) {
|
||||
menu[menu_items-1]->command = MENU_GENWWWURLS;
|
||||
}
|
||||
} else if (strncasecmp(buffer, "SECLEVEL", 8) == 0) {
|
||||
menu[menu_items-1]->seclevel = atoi(&buffer[9]);
|
||||
} else if (strncasecmp(buffer, "DATA", 4) == 0) {
|
||||
@@ -531,6 +534,9 @@ int menu_system(char *menufile) {
|
||||
s_printf(get_string(6));
|
||||
s_getc();
|
||||
break;
|
||||
case MENU_GENWWWURLS:
|
||||
genurls();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@@ -266,7 +266,7 @@ int inst_user(struct user_record *user) {
|
||||
"exteditor INTEGER,"
|
||||
"bwavestyle INTEGER,"
|
||||
"signature TEXT,"
|
||||
"autosig INT);";
|
||||
"autosig INTEGER);";
|
||||
|
||||
char *insert_sql = "INSERT INTO users (loginname, password, salt, firstname,"
|
||||
"lastname, email, location, sec_level, last_on, time_left, cur_mail_conf, cur_mail_area, cur_file_dir, cur_file_sub, times_on, bwavepktno, archiver, protocol, nodemsgs, codepage, exteditor, bwavestyle, signature, autosig) VALUES(?,?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
31
src/www.c
31
src/www.c
@@ -415,6 +415,7 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url
|
||||
const char *val;
|
||||
int skip;
|
||||
char *replyid;
|
||||
char *filename;
|
||||
// char *static_buffer;
|
||||
|
||||
if (strcmp(method, "GET") == 0) {
|
||||
@@ -826,6 +827,36 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
} else if (strncasecmp(url, "/files/", 7) == 0) {
|
||||
filename = www_decode_hash(&url[7]);
|
||||
if (filename != NULL) {
|
||||
if (stat(filename, &s) == 0 && S_ISREG(s.st_mode)) {
|
||||
fno = open(buffer, O_RDONLY);
|
||||
if (fno != -1) {
|
||||
|
||||
response = MHD_create_response_from_fd(s.st_size, fno);
|
||||
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, mime);
|
||||
sprintf(buffer, "%ld", s.st_size);
|
||||
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_LENGTH, buffer);
|
||||
snprintf(buffer, PATH_MAX, "attachment; filename=\"%s\"", basename(filename));
|
||||
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_DISPOSITION, buffer);
|
||||
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response (response);
|
||||
free(header);
|
||||
free(footer);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
if (www_404(header, footer, connection) != 0) {
|
||||
free(header);
|
||||
free(footer);
|
||||
return MHD_NO;
|
||||
}
|
||||
free(header);
|
||||
free(footer);
|
||||
return MHD_YES;
|
||||
} else {
|
||||
if (www_404(header, footer, connection) != 0) {
|
||||
free(header);
|
||||
|
237
src/www_files.c
Normal file
237
src/www_files.c
Normal file
@@ -0,0 +1,237 @@
|
||||
#if defined(ENABLE_WWW)
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sqlite3.h>
|
||||
#include <libgen.h>
|
||||
#include "bbs.h"
|
||||
#include "../deps/hashids/hashids.h"
|
||||
|
||||
extern struct bbs_config conf;
|
||||
extern struct user_record *gUser;
|
||||
|
||||
void www_expire_old_links() {
|
||||
char buffer[PATH_MAX];
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *res;
|
||||
int rc;
|
||||
char sql[] = "delete from wwwhash where expire <= ?";
|
||||
char *ret;
|
||||
time_t now = time(NULL);
|
||||
|
||||
snprintf(buffer, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path);
|
||||
|
||||
rc = sqlite3_open(buffer, &db);
|
||||
if (rc != SQLITE_OK) {
|
||||
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
||||
return;
|
||||
}
|
||||
sqlite3_busy_timeout(db, 5000);
|
||||
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
|
||||
if (rc != SQLITE_OK) {
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
sqlite3_bind_int(res, 1, now);
|
||||
sqlite3_step(res);
|
||||
sqlite3_finalize(res);
|
||||
sqlite3_close(db);
|
||||
}
|
||||
|
||||
int www_check_hash_expired(char *hash) {
|
||||
char buffer[PATH_MAX];
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *res;
|
||||
int rc;
|
||||
time_t now = time(NULL);
|
||||
char sql[] = "select id from wwwhash where hash = ? and expire > ?";
|
||||
snprintf(buffer, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path);
|
||||
rc = sqlite3_open(buffer, &db);
|
||||
if (rc != SQLITE_OK) {
|
||||
return 1;
|
||||
}
|
||||
sqlite3_busy_timeout(db, 5000);
|
||||
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
|
||||
if (rc != SQLITE_OK) {
|
||||
sqlite3_close(db);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sqlite3_bind_text(res, 1, hash, -1, 0);
|
||||
sqlite3_bind_int(res, 2, now);
|
||||
|
||||
if (sqlite3_step(res) == SQLITE_ROW) {
|
||||
sqlite3_finalize(res);
|
||||
sqlite3_close(db);
|
||||
return 0;
|
||||
}
|
||||
sqlite3_finalize(res);
|
||||
sqlite3_close(db);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void www_add_hash_to_db(char *hash, time_t expiry) {
|
||||
char buffer[PATH_MAX];
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *res;
|
||||
int rc;
|
||||
char csql[] = "create table if not exists wwwhash (id INTEGER PRIMARY KEY, hash TEXT, expiry INTEGER)";
|
||||
char chsql[] = "select id from wwwhash where hash = ?";
|
||||
char usql[] = "update wwwhash SET expiry = ? WHERE hash = ?";
|
||||
char isql[] = "insert into wwwhash (hash, expiry) values(?, ?)";
|
||||
|
||||
char *ret;
|
||||
char *err_msg = 0;
|
||||
|
||||
snprintf(buffer, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path);
|
||||
|
||||
rc = sqlite3_open(buffer, &db);
|
||||
if (rc != SQLITE_OK) {
|
||||
return;
|
||||
}
|
||||
sqlite3_busy_timeout(db, 5000);
|
||||
|
||||
rc = sqlite3_exec(db, csql, 0, 0, &err_msg);
|
||||
if (rc != SQLITE_OK) {
|
||||
|
||||
dolog("SQL error: %s", err_msg);
|
||||
|
||||
sqlite3_free(err_msg);
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
|
||||
// first check if hash is in database
|
||||
rc = sqlite3_prepare_v2(db, chsql, -1, &res, 0);
|
||||
if (rc != SQLITE_OK) {
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
sqlite3_bind_text(res, 1, hash, -1, 0);
|
||||
rc = sqlite3_step(res);
|
||||
if (rc == SQLITE_ROW) {
|
||||
// if so, update hash
|
||||
sqlite3_finalize(res);
|
||||
rc = sqlite3_prepare_v2(db, usql, -1, &res, 0);
|
||||
if (rc != SQLITE_OK) {
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
sqlite3_bind_int(res, 1, expiry);
|
||||
sqlite3_bind_text(res, 2, hash, -1, 0);
|
||||
sqlite3_step(res);
|
||||
sqlite3_finalize(res);
|
||||
sqlite3_close(db);
|
||||
|
||||
return;
|
||||
}
|
||||
// if not add hash
|
||||
sqlite3_finalize(res);
|
||||
rc = sqlite3_prepare_v2(db, isql, -1, &res, 0);
|
||||
if (rc != SQLITE_OK) {
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
sqlite3_bind_text(res, 1, hash, -1, 0);
|
||||
sqlite3_bind_int(res, 2, expiry);
|
||||
sqlite3_step(res);
|
||||
sqlite3_finalize(res);
|
||||
sqlite3_close(db);
|
||||
}
|
||||
|
||||
char *www_decode_hash(char *hash) {
|
||||
long long unsigned numbers[4];
|
||||
int dir, sub, fid, uid;
|
||||
hashids_t *hashids = hashids_init(conf.bbs_name);
|
||||
char buffer[PATH_MAX];
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *res;
|
||||
int rc;
|
||||
char sql[] = "select filename from files where approved = 1 and id = ?";
|
||||
char *ret;
|
||||
|
||||
if (www_check_hash_expired(hash)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hashids_decode(hashids, hash, numbers) != 4) {
|
||||
hashids_free(hashids);
|
||||
return NULL;
|
||||
}
|
||||
hashids_free(hashids);
|
||||
|
||||
uid = (int)numbers[0];
|
||||
dir = (int)numbers[1];
|
||||
sub = (int)numbers[2];
|
||||
fid = (int)numbers[3];
|
||||
|
||||
if (dir >= conf.file_directory_count || sub >= conf.file_directories[dir]->file_sub_count) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// TODO: check security level...
|
||||
|
||||
if (conf.file_directories[dir]->sec_level < )
|
||||
#endif
|
||||
// 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);
|
||||
if (rc != SQLITE_OK) {
|
||||
dolog("Cannot open database: %s", sqlite3_errmsg(db));
|
||||
return NULL;
|
||||
}
|
||||
sqlite3_busy_timeout(db, 5000);
|
||||
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
|
||||
if (rc != SQLITE_OK) {
|
||||
sqlite3_close(db);
|
||||
return NULL;
|
||||
}
|
||||
sqlite3_bind_int(res, 1, fid);
|
||||
if (sqlite3_step(res) == SQLITE_ROW) {
|
||||
ret = strdup(sqlite3_column_text(res, 0));
|
||||
sqlite3_finalize(res);
|
||||
sqlite3_close(db);
|
||||
|
||||
return ret;
|
||||
}
|
||||
sqlite3_finalize(res);
|
||||
sqlite3_close(db);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *www_create_link(int dir, int sub, int fid) {
|
||||
char url[PATH_MAX];
|
||||
char *ret;
|
||||
char *hashid;
|
||||
int sizereq;
|
||||
time_t expiry;
|
||||
|
||||
hashids_t *hashids = hashids_init(conf.bbs_name);
|
||||
|
||||
sizereq = hashids_estimate_encoded_size_v(hashids, 4, gUser->id, dir, sub, fid);
|
||||
|
||||
hashid = (char *)malloc(sizereq);
|
||||
|
||||
if (hashids_encode_v(hashids, hashid, 4, gUser->id, dir, sub, fid) == 0) {
|
||||
hashids_free(hashids);
|
||||
free(hashid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hashids_free(hashids);
|
||||
|
||||
snprintf(url, PATH_MAX, "%sfiles/%s", conf.www_url, hashid);
|
||||
|
||||
// add link into hash database
|
||||
expiry = time(NULL) + 86400;
|
||||
www_add_hash_to_db(hashid, expiry);
|
||||
|
||||
free(hashid);
|
||||
|
||||
ret = strdup(url);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user