summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ColaBBS_to_PttBBS/README36
-rw-r--r--ColaBBS_to_PttBBS/cntDIR.c40
-rw-r--r--ColaBBS_to_PttBBS/cntarticle.pl22
-rw-r--r--ColaBBS_to_PttBBS/cntbrd.c114
-rw-r--r--ColaBBS_to_PttBBS/cnthomeDIR.c45
-rw-r--r--ColaBBS_to_PttBBS/cnthomedir.pl12
-rw-r--r--ColaBBS_to_PttBBS/cntmail.pl23
-rw-r--r--ColaBBS_to_PttBBS/cntpasswd.c35
8 files changed, 327 insertions, 0 deletions
diff --git a/ColaBBS_to_PttBBS/README b/ColaBBS_to_PttBBS/README
new file mode 100644
index 00000000..9e6a2588
--- /dev/null
+++ b/ColaBBS_to_PttBBS/README
@@ -0,0 +1,36 @@
+There're some tools for transfering data from ColaBBS
+(http://lh.twbbs.org/) to PttBBS (http://ptt.cc). Since ColaBBS
+doesn't provide its source code or any file spec, there's no good way
+to do this. I hacked the data structures with only VERY LITTLE
+information directly from files, and these may NOT work. You sould NOT
+use if you don't have programming background, or contact(make a
+offer?) me in2 _AT_ in2home.org.
+
+please follow the step:
+1. backup your ColaBBS.
+2. install a new PttBBS
+ (see https://opensvn.csie.org/pttbbs/trunk/pttbbs/docs/INSTALL for
+ details)
+ please do NOT do the following to a existed bbs!
+3. shutdown the bbs and clean all shared-memory if it's running.
+4. copy all .c and .pl programs into your ~bbs/pttbbs/util/. then
+ compile them: `make cntDIR cntbrd cnthomeDIR cntpasswd`
+5. transfer boards:
+ cd _COLABBS_/boards/; \
+ perl -e "system('mv $_ ~/boards/'.
+ substr($_, 0, 1).'/'.$_) foreach( <*> )"
+
+ cd /home/bbs/boards; perl cntarticle.pl boards/*/*; \
+ apply "mv %1/.DIR %1/.DIR.colabbs; cntDIR < %1/.DIR.colabbs >
+ %1/.DIR" */*
+ cntbrd < _COLABBS_/boards/.BOARDS > ~/.BRD
+6. transfer password file:
+ cntpasswd < _COLABBS_/.PASSWDS > ~/.PASSWDS
+7. transfer mails
+ cd _COLABBS_/home; cnthomedir.pl
+ cd ~/home/;
+ apply "mv %1/mail/* %1/" */*; \
+ apply "mv %1/mail/.DIR %1/.DIR.colabbs" */*; \
+ apply "rmdir %1/mail" */*; \
+ apply "cnthomeDIR < %1/.DIR.colabbs > %1/.DIR"; \
+ cntarticle.pl */*
diff --git a/ColaBBS_to_PttBBS/cntDIR.c b/ColaBBS_to_PttBBS/cntDIR.c
new file mode 100644
index 00000000..f71aa706
--- /dev/null
+++ b/ColaBBS_to_PttBBS/cntDIR.c
@@ -0,0 +1,40 @@
+#include "bbs.h"
+/*
+ usage: apply "mv %1/.DIR %1/.DIR.colabbs;
+ ./cntDIR < %1/.DIR.colabbs > %1/.DIR;
+ rm %1/.DIR.colabbs"
+ ~/boards/ * / *
+ ^ ^ ^ <- please ignore the spaces
+*/
+
+typedef struct {
+ char filename[FNLEN]; /* M.9876543210.A */
+ char pad0[78-FNLEN];
+ char owner[IDLEN + 2]; /* uid[.] */
+ char pad1[68];
+ char title[65];
+ char pad2[31];
+} ffh_t;
+int main(int argc, char **argv)
+{
+ ffh_t ffh;
+ fileheader_t fh;
+
+ time_t t;
+ struct tm *tm;
+
+ memset(&fh, 0, sizeof(fh));
+ while( read(0, &ffh, sizeof(ffh)) == sizeof(ffh) ){
+ if( !ffh.filename[0] )
+ continue;
+ strlcpy(fh.filename, ffh.filename, sizeof(fh.filename));
+ strlcpy(fh.title, ffh.title, sizeof(fh.title));
+ strlcpy(fh.owner, ffh.owner, sizeof(fh.owner));
+
+ t = atoi(&fh.filename[2]);
+ tm = localtime(&t);
+ sprintf(fh.date, "%2d/%02d", tm->tm_mon + 1, tm->tm_mday);
+ write(1, &fh, sizeof(fh));
+ }
+ return 0;
+}
diff --git a/ColaBBS_to_PttBBS/cntarticle.pl b/ColaBBS_to_PttBBS/cntarticle.pl
new file mode 100644
index 00000000..0567d378
--- /dev/null
+++ b/ColaBBS_to_PttBBS/cntarticle.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+use IO::All;
+die "usage: cntarticle.pl [base dir]"
+ if( !@ARGV );
+
+foreach( @ARGV ){
+ print "converting: $_\n";
+ convert($_)
+ foreach( <$_/M.*.A> );
+}
+
+sub convert
+{
+ my($fn) = @_;
+ $content < io($fn);
+ $content =~ s/\r//gs;
+ $content =~ s/^.*?m 作者 .*?m (.*\))\s+\S+? 信區 .*?m (\S+).*/作者: $1 看板: $2/m;
+ $content =~ s/^.*?m 標題 .*?m (.*?)\s+\S+m/標題: $1/m;
+ $content =~ s/^.*?m 時間 .*?m (.*?)\s+\S+m/時間: $1/m;
+ $content =~ s/^\e\[36m────────────────────────────────────────\e\[m\n//m;
+ "$content\n" > io($fn);
+}
diff --git a/ColaBBS_to_PttBBS/cntbrd.c b/ColaBBS_to_PttBBS/cntbrd.c
new file mode 100644
index 00000000..23f28849
--- /dev/null
+++ b/ColaBBS_to_PttBBS/cntbrd.c
@@ -0,0 +1,114 @@
+#include "bbs.h"
+/* usage: ./cntbrd < ColaBBS/.BOARDS > ~/.BRD */
+
+typedef struct {
+ char brdname[13];
+ char pad[148];
+ char title[49];
+ char pad2[46];
+} fbrd_t;
+
+int main(int argc, char **argv)
+{
+ fbrd_t fbh;
+ boardheader_t bh;
+#if 0
+ int i;
+ read(0, &fbh, sizeof(fbh));
+ for( i = 0 ; i < sizeof(fbh) ; ++i )
+ printf("%03d: %d(%c)\n", i, fbh.pad[i], fbh.pad[i]);
+ return 0;
+#endif
+
+ memset(&bh, 0, sizeof(bh));
+ strcpy(bh.brdname, "SYSOP");
+ strcpy(bh.title, "嘰哩 ◎站長好!");
+ bh.brdattr = BRD_POSTMASK | BRD_NOTRAN | BRD_NOZAP;
+ bh.level = 0;
+ bh.gid = 2;
+ write(1, &bh, sizeof(bh));
+
+ strcpy(bh.brdname, "1...........");
+ strcpy(bh.title, ".... Σ中央政府 《高壓危險,非人可敵》");
+ bh.brdattr = BRD_GROUPBOARD;
+ bh.level = PERM_SYSOP;
+ bh.gid = 1;
+ write(1, &bh, sizeof(bh));
+
+ strcpy(bh.brdname, "junk");
+ strcpy(bh.title, "發電 ◎雜七雜八的垃圾");
+ bh.brdattr = BRD_NOTRAN;
+ bh.level = PERM_SYSOP;
+ bh.gid = 2;
+ write(1, &bh, sizeof(bh));
+
+ strcpy(bh.brdname, "Security");
+ strcpy(bh.title, "發電 ◎站內系統安全");
+ bh.brdattr = BRD_NOTRAN;
+ bh.level = PERM_SYSOP;
+ bh.gid = 2;
+ write(1, &bh, sizeof(bh));
+
+ strcpy(bh.brdname, "2...........");
+ strcpy(bh.title, ".... Σ市民廣場 報告 站長 ㄜ!");
+ bh.brdattr = BRD_GROUPBOARD;
+ bh.level = 0;
+ bh.gid = 1;
+ write(1, &bh, sizeof(bh));
+
+ strcpy(bh.brdname, "ALLPOST");
+ strcpy(bh.title, "嘰哩 ◎跨板式LOCAL新文章");
+ bh.brdattr = BRD_POSTMASK | BRD_NOTRAN;
+ bh.level = PERM_SYSOP;
+ bh.gid = 5;
+ write(1, &bh, sizeof(bh));
+
+ strcpy(bh.brdname, "deleted");
+ strcpy(bh.title, "嘰哩 ◎資源回收筒");
+ bh.brdattr = BRD_NOTRAN;
+ bh.level = PERM_BM;
+ bh.gid = 5;
+ write(1, &bh, sizeof(bh));
+
+ strcpy(bh.brdname, "Note");
+ strcpy(bh.title, "嘰哩 ◎動態看板及歌曲投稿");
+ bh.brdattr = BRD_NOTRAN;
+ bh.level = 0;
+ bh.gid = 5;
+ write(1, &bh, sizeof(bh));
+
+ strcpy(bh.brdname, "Record");
+ strcpy(bh.title, "嘰哩 ◎我們的成果");
+ bh.brdattr = BRD_NOTRAN | BRD_POSTMASK;
+ bh.level = 0;
+ bh.gid = 5;
+ write(1, &bh, sizeof(bh));
+
+ strcpy(bh.brdname, "WhoAmI");
+ strcpy(bh.title, "嘰哩 ◎呵呵,猜猜我是誰!");
+ bh.brdattr = BRD_NOTRAN;
+ bh.level = 0;
+ bh.gid = 5;
+ write(1, &bh, sizeof(bh));
+
+ strcpy(bh.brdname, "EditExp");
+ strcpy(bh.title, "嘰哩 ◎範本精靈投稿區");
+ bh.brdattr = BRD_NOTRAN;
+ bh.level = 0;
+ bh.gid = 5;
+ write(1, &bh, sizeof(bh));
+
+ while( read(0, &fbh, sizeof(fbh)) == sizeof(fbh) ){
+ if( !fbh.brdname[0] || strcasecmp(fbh.brdname, "sysop") == 0 )
+ continue;
+ memset(&bh, 0, sizeof(bh));
+ strlcpy(bh.brdname, fbh.brdname, sizeof(bh.brdname));
+ strlcpy(bh.title, "轉換 ◎", sizeof(bh.title));
+ strlcpy(&bh.title[7], fbh.title, sizeof(bh.title));
+ bh.brdattr = BRD_NOTRAN;
+ bh.level = 0;
+ bh.gid = 2;
+ write(1, &bh, sizeof(bh));
+ }
+ return 0;
+}
diff --git a/ColaBBS_to_PttBBS/cnthomeDIR.c b/ColaBBS_to_PttBBS/cnthomeDIR.c
new file mode 100644
index 00000000..a0ca6c8d
--- /dev/null
+++ b/ColaBBS_to_PttBBS/cnthomeDIR.c
@@ -0,0 +1,45 @@
+#include "bbs.h"
+/* please run cnthomedir.pl first!
+ cd home/; apply "mv %1/mail/* %1/" * / *
+ apply "mv %1/mail/.DIR %1/.DIR.colabbs" * / *
+ apply "rmdir %1/mail" * / *
+ apply "cnthomeDIR < %1/.DIR.colabbs > %1/.DIR" * / *
+*/
+
+typedef struct {
+ char filename[FNLEN]; /* M.9876543210.A */
+ char pad0[80-FNLEN];
+ char owner[IDLEN + 2]; /* uid[.] */
+ char pad1[66];
+ char title[65];
+ char pad2[31];
+} ffh_t;
+int main(int argc, char **argv)
+{
+ ffh_t ffh;
+ fileheader_t fh;
+
+ time_t t;
+ struct tm *tm;
+ int i;
+
+ memset(&fh, 0, sizeof(fh));
+ while( read(0, &ffh, sizeof(ffh)) == sizeof(ffh) ){
+ if( !ffh.filename[0] )
+ continue;
+ strlcpy(fh.filename, ffh.filename, sizeof(fh.filename));
+ strlcpy(fh.title, ffh.title, sizeof(fh.title));
+ strlcpy(fh.owner, ffh.owner, sizeof(fh.owner));
+ for( i = 0 ; i < sizeof(fh.owner) ; ++i )
+ if( fh.owner[i] == ' ' ){
+ fh.owner[i] = 0;
+ break;
+ }
+
+ t = atoi(&fh.filename[2]);
+ tm = localtime(&t);
+ sprintf(fh.date, "%2d/%02d", tm->tm_mon + 1, tm->tm_mday);
+ write(1, &fh, sizeof(fh));
+ }
+ return 0;
+}
diff --git a/ColaBBS_to_PttBBS/cnthomedir.pl b/ColaBBS_to_PttBBS/cnthomedir.pl
new file mode 100644
index 00000000..acb6fd28
--- /dev/null
+++ b/ColaBBS_to_PttBBS/cnthomedir.pl
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+# usage: cd ColaBBS/home; perl cnthomedir.pl
+use IO::All;
+foreach( <*> ){
+ next if( !-d $_ || /\./ );
+ $USERDATA < io("$_/USERDATA.DAT");
+ ($userid) = $USERDATA =~ /^(\w+)/;
+ $c = substr($userid, 0, 1);
+
+ `mv ~/home/$c/$userid ~/tmp/; mv $_ ~/home/$c/$userid`;
+ print "$_ => $userid\n";
+}
diff --git a/ColaBBS_to_PttBBS/cntmail.pl b/ColaBBS_to_PttBBS/cntmail.pl
new file mode 100644
index 00000000..a5d6396f
--- /dev/null
+++ b/ColaBBS_to_PttBBS/cntmail.pl
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+use IO::All;
+die "usage: cntarticle.pl [base dir]"
+ if( !@ARGV );
+
+foreach( @ARGV ){
+ print "converting: $_\n";
+ convert($_)
+ foreach( <$_/M.*.A> );
+}
+
+sub convert
+{
+ my($fn) = @_;
+ $content < io($fn);
+ $content =~ s/\r//gs;
+ $content =~ s/\^R//gs;
+ $content =~ s/^.*?m 作者 .*?m (.*\))\s+$/作者: $1/m;
+ $content =~ s/^.*?m 標題 .*?m (.*?)\s+\S+m/標題: $1/m;
+ $content =~ s/^.*?m 時間 .*?m (.*?)\s+\S+m/時間: $1/m;
+ $content =~ s/^\e\[36m────────────────────────────────────────\e\[m\n//m;
+ "$content\n" > io($fn);
+}
diff --git a/ColaBBS_to_PttBBS/cntpasswd.c b/ColaBBS_to_PttBBS/cntpasswd.c
new file mode 100644
index 00000000..ca0f419e
--- /dev/null
+++ b/ColaBBS_to_PttBBS/cntpasswd.c
@@ -0,0 +1,35 @@
+#include "bbs.h"
+/* usage: ./cntpasswd < ColaBBS/.PASSWDS > ~/.PASSWDS */
+
+typedef struct {
+ char userid[IDLEN + 1];
+ char pad0[1];
+ char passwd[PASSLEN];
+ char nick[24];
+ char pad1[16];
+ char name[20];
+ char pad2[424];
+} fuserect_t;
+
+int main(int argc, char **argv)
+{
+ fuserect_t fu;
+ userec_t u;
+ memset(&u, 0, sizeof(u));
+ while( read(0, &fu, sizeof(fu)) == sizeof(fu) ){
+#if 0
+ printf("(%s), (%s), (%s), (%s)\n",
+ fu.userid, fu.passwd, fu.nick, fu.name);
+#endif
+ if( !fu.userid[0] )
+ continue;
+
+ memset(&u, 0, sizeof(u));
+ strlcpy(u.userid, fu.userid, sizeof(u.userid));
+ strlcpy(u.passwd, fu.passwd, sizeof(u.passwd));
+ strlcpy(u.realname, fu.name, sizeof(u.realname));
+ strlcpy(u.username, fu.nick, sizeof(u.username));
+ write(1, &u, sizeof(u));
+ }
+ return 0;
+}