diff options
-rw-r--r-- | pttbbs/util/Makefile | 3 | ||||
-rw-r--r-- | pttbbs/util/redir.c | 159 |
2 files changed, 161 insertions, 1 deletions
diff --git a/pttbbs/util/Makefile b/pttbbs/util/Makefile index 58edfa4b..6b122995 100644 --- a/pttbbs/util/Makefile +++ b/pttbbs/util/Makefile @@ -22,7 +22,8 @@ CPROG_WITH_UTIL= \ outmail chkhbf merge_dir \ angel gamblegive \ chesscountry tunepasswd buildir xchatd \ - uhash_loader timecap_buildref showuser removebm + uhash_loader timecap_buildref showuser removebm \ + redir # 下面是 C++ 的程式 CPP_WITH_UTIL= \ diff --git a/pttbbs/util/redir.c b/pttbbs/util/redir.c new file mode 100644 index 00000000..aea708dd --- /dev/null +++ b/pttbbs/util/redir.c @@ -0,0 +1,159 @@ +/* $Id: timecap_buildref.c 5198 2010-11-01 09:32:43Z piaip $ */ + +#include "bbs.h" +#define SKIP_FILE_CHECK + +int in_spam(const fileheader_t *fh) { + const char *title = fh->title; + return strcasestr(title, "[SPAM] FILL YOUR SPAM HERE") || + + // legacy return receipt + (strcmp(fh->owner, "MAILER-DAEMON") == 0 && + strcmp(fh->title, "Undelivered Mail Returned to Sender") == 0) || + + // let's also remove dangerous birthday links + (strcmp(fh->owner, "批踢踢實業坊") == 0 && + strcmp(fh->title, "!! 生日快樂 !!") == 0) || + 0; +} + +int process(FILE *fin, FILE *fout, const char *index_path, + int *pkeep, int remove_spam, int remove_days, + int remove_deleted) { + + char file_path[PATHLEN]; + fileheader_t fh; + int num_remove = 0; + int now = time(0); + + *pkeep = 0; + while (fread(&fh, sizeof(fh), 1, fin) == 1) { + int should_remove = 0; + // build file name + setdirpath(file_path, index_path, fh.filename); + + if (!should_remove && remove_spam && in_spam(&fh)) + should_remove = 1; + + if (!should_remove && remove_days > 0 && strlen(fh.filename) > 2 && + fh.filename[1] == '.') { + int ts = atoi(fh.filename + 2); + if (ts < now - 86400 * remove_days) + should_remove = 1; + } + + if (!should_remove && remove_deleted && !dashf(file_path)) { + should_remove = 1; + } + + if (should_remove) { + if (!fout) + return 1; + + printf("%s: %s %s\n", file_path, fh.filename, fh.title); + unlink(file_path); + num_remove++; + if (!fout) + return 1; + continue; + } + (*pkeep)++; + if (fout) + fwrite(&fh, sizeof(fh), 1, fout); + } + return num_remove; +} + +void die_usage(const char *myname) { + printf("usage: %s [-options] PATH_TO_FN_DIR\n" + " -s: remove spam\n" + " -e: check existence\n" + " -d days: remove posts > days\n" + " -v: verbose\n" + , myname); + exit(1); +} + +int main(int argc, char **argv) +{ + char index_path[PATHLEN]; + const char *dirpath, *myname = argv[0]; + int opt; + int num_keep = 0, num_remove = 0; + FILE *fin; + int remove_spam = 0, remove_days = 0, remove_deleted = 0; + int verbose = 0; + + while ((opt = getopt(argc, argv, "sedv:")) != -1) { + switch (opt) { + case 's': + remove_spam = 1; + break; + + case 'd': + remove_days = atoi(optarg); + break; + + case 'e': + remove_deleted = 1; + break; + + case 'v': + verbose++; + break; + + default: + die_usage(myname); + break; + } + } + + if (optind != argc - 1 || remove_days < 0 || optind < 2) { + die_usage(myname); + } + + dirpath = argv[optind]; + if (!dashd(dirpath)) { + fprintf(stderr, "invalid directory: %s\n", dirpath); + return 1; + } + + snprintf(index_path, sizeof(index_path), "%s/%s", dirpath, FN_DIR); + if (dashs(index_path) <= 0) { + // no archive. abort. + // fprintf(stderr, "missing time capsule archive: %s\n", index_path); + return 1; + } + + fin = fopen(index_path, "rb"); + if (!fin) { + fprintf(stderr, "failed to open index file.\n"); + return 2; + } + + if ((num_remove = process(fin, NULL, index_path, &num_keep, + remove_spam, remove_days, remove_deleted))) { + char tmp_index_path[PATHLEN]; + FILE *fout; + + strlcpy(tmp_index_path, index_path, sizeof(tmp_index_path)); + strlcat(tmp_index_path, ".tmp", sizeof(tmp_index_path)); + fout = fopen(tmp_index_path, "wb"); + if (!fout) { + fprintf(stderr, "failed to create ouptut file.\n"); + return 2; + } + rewind(fin); + num_remove = process(fin, fout, index_path, &num_keep, + remove_spam, remove_days, remove_deleted); + fclose(fout); + fclose(fin); + Rename(tmp_index_path, index_path); + } else { + fclose(fin); + } + + printf("%s: %d entries kept, %d entries removed.\n", + index_path, num_keep, num_remove); + return 0; +} |