From 42f5e92961b1077da7f085641ca450b7f193d668 Mon Sep 17 00:00:00 2001
From: piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>
Date: Sat, 7 Apr 2012 01:17:46 +0000
Subject: Add redir utility.

git-svn-id: http://opensvn.csie.org/pttbbs/trunk@5606 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
---
 pttbbs/util/Makefile |   3 +-
 pttbbs/util/redir.c  | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 161 insertions(+), 1 deletion(-)
 create mode 100644 pttbbs/util/redir.c

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
 
 # �U���O 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;
+}
-- 
cgit v1.2.3