summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--web/.cvsignore3
-rw-r--r--web/Makefile6
-rw-r--r--web/Makefile.old120
-rw-r--r--web/Makefile.tmpl16
-rw-r--r--web/Makefile.tmpl.bak17
-rwxr-xr-xweb/args.c228
-rw-r--r--web/board.c39
-rw-r--r--web/chmod1
-rwxr-xr-xweb/l1
-rw-r--r--web/mail.c6
-rw-r--r--web/mod_ptt.c284
-rw-r--r--web/mod_ptt.h13
-rwxr-xr-xweb/mytime.h189
-rwxr-xr-xweb/parse_html.c294
-rw-r--r--web/post.c6
-rwxr-xr-xweb/r1
-rwxr-xr-xweb/s1
-rwxr-xr-xweb/stuff.c269
-rwxr-xr-xweb/t1
-rw-r--r--web/user.c6
20 files changed, 1501 insertions, 0 deletions
diff --git a/web/.cvsignore b/web/.cvsignore
new file mode 100644
index 00000000..33ec1741
--- /dev/null
+++ b/web/.cvsignore
@@ -0,0 +1,3 @@
+*.o
+*.so
+*.a
diff --git a/web/Makefile b/web/Makefile
new file mode 100644
index 00000000..095610b3
--- /dev/null
+++ b/web/Makefile
@@ -0,0 +1,6 @@
+all: mod_ptt.c mod_ptt.h
+ apxs -I ../include -c mod_ptt.c ../util/util_cache.c ../util/util_passwd.c ../util/util_record.c
+ cp mod_ptt.so /usr/local/libexec/apache/mod_ptt.so
+ chmod 775 /usr/local/libexec/apache/mod_ptt.so
+clean:
+ rm -f *.o *.a *.so
diff --git a/web/Makefile.old b/web/Makefile.old
new file mode 100644
index 00000000..db2735bf
--- /dev/null
+++ b/web/Makefile.old
@@ -0,0 +1,120 @@
+##
+## Apache Makefile, automatically generated by Configure script.
+## Hand-edited changes will be lost if the Configure script is re-run.
+## Sources: - ../../Makefile.config (via Configuration)
+## - ./Makefile.tmpl
+##
+
+##
+## Inherited Makefile options from Configure script
+## (Begin of automatically generated section)
+##
+SRCDIR=../..
+EXTRA_CFLAGS=
+EXTRA_LDFLAGS=
+EXTRA_LIBS=
+EXTRA_INCLUDES=
+EXTRA_DEPS=
+OSDIR=$(SRCDIR)/os/unix
+INCDIR=$(SRCDIR)/include
+INCLUDES0=-I$(OSDIR) -I$(INCDIR) -I../$(INCDIR)
+SHELL=/bin/sh
+OS=FreeBSD 4.6
+CC=gcc
+CPP=gcc -E
+TARGET=httpd
+OPTIM=
+CFLAGS1= -funsigned-char -DUSE_EXPAT -I$(SRCDIR)/lib/expat-lite -DNO_DL_NEEDED
+INCLUDES1=
+LIBS_SHLIB=
+LDFLAGS1=
+MFLAGS_STATIC=
+REGLIB=
+EXPATLIB=lib/expat-lite/libexpat.a
+RANLIB=ranlib
+LIBS1= -lcrypt
+##
+## (End of automatically generated section)
+##
+
+##
+## Default Makefile options from Configure script
+## (Begin of automatically generated section)
+##
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+INCDIR=$(SRCDIR)/include
+OBJS=mod_ptt.o parse_html.o
+BBSLIBS=util_cache.o util_passwd.o util_record.o
+LIB=libptt.a
+SHLIBS=
+OBJS_PIC=
+
+all: lib shlib
+
+lib: $(LIB)
+
+shlib: $(SHLIBS)
+
+dummy $(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS) $(BBSLIBS)
+ $(RANLIB) $@
+
+.SUFFIXES: .o .so .dll
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+.c.so:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $< && mv $*.o $*.lo
+ $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $@ $*.lo $(LIBS_SHLIB)
+
+clean:
+ rm -f $(LIB) $(OBJS) $(SHLIBS) $(OBJS_PIC)
+
+distclean: clean
+ rm -f Makefile
+
+# NOT FOR END USERS!
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+##
+## (End of automatically generated section)
+##
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+# DO NOT REMOVE
+mod_ptt.o: mod_ptt.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/util_script.h \
+ /home/bbs/pttbbs/include/bbs.h
+
+parse_html.o: parse_html.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/util_script.h \
+ /home/bbs/pttbbs/include/bbs.h
diff --git a/web/Makefile.tmpl b/web/Makefile.tmpl
new file mode 100644
index 00000000..83ed1e84
--- /dev/null
+++ b/web/Makefile.tmpl
@@ -0,0 +1,16 @@
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+BBSLIBS= util_cache.o util_record.o util_passwd.o
+
+# DO NOT REMOVE
+mod_ptt.o: mod_ptt.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/util_script.h
diff --git a/web/Makefile.tmpl.bak b/web/Makefile.tmpl.bak
new file mode 100644
index 00000000..e686b7a9
--- /dev/null
+++ b/web/Makefile.tmpl.bak
@@ -0,0 +1,17 @@
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+BBSLIBS= util_cache.o util_record.o util_passwd.o
+
+# DO NOT REMOVE
+mod_ptt.o: mod_ptt.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/util_script.h
diff --git a/web/args.c b/web/args.c
new file mode 100755
index 00000000..02e0fad0
--- /dev/null
+++ b/web/args.c
@@ -0,0 +1,228 @@
+/* 使用方法: 自己先用 r->method_number 判斷是 M_GET 或 M_POST
+ */
+#include "mod_ptt.h"
+
+unsigned char xtoc(char ch1, char ch2) {
+ unsigned char d, up1, up2;
+
+ if (!isxdigit(ch1) || !isxdigit(ch2)) return ' ';
+
+ up1 = toupper(ch1);
+ up2 = toupper(ch2);
+
+ if (up1>='0' && up1<='9') d = up1-'0';
+ else d = up1-'A'+10;
+ d <<= 4;
+ if (up2>='0' && up2<='9') d += up2-'0';
+ else d += up2-'A'+10;
+
+ return d;
+}
+
+char * cstoxs(pool *p, char *str)
+{
+ char * newstr = pstrdup(p,""), *po = str;
+
+ for(po = str; *po; po++)
+ {
+ if(isprint(*po) && *po!=' ') newstr=psprintf(p, "%s%c", newstr,*po);
+ else newstr=psprintf(p, "%s%%%X", newstr, *po& 0xFF);
+ }
+ return newstr;
+}
+
+int // Ptt: 我重寫拿掉mygetchar 並加上fileupload的功能
+inital_postdata(request_rec *r, int *fileupload, char *boundary,
+ char **data)
+{
+ char *buf, *mb;
+ int size, off = 0, len_read;
+ void (*handler)();
+
+ buf = table_get(r->subprocess_env,"CONTENT_TYPE");
+ if(!buf ||
+ (strncasecmp(buf,"application/x-www-form-urlencoded",33) &&
+ strncasecmp(buf,"multipart/form-data",19)))
+ return -1;
+
+ if(!strncasecmp(buf,"multipart/form-data",19)) {
+ if(!fileupload) return -1;
+ *fileupload=1;
+ mb = strchr(buf,'=');
+ if(mb) {
+ strcpy(boundary,mb+1);
+ strtok(boundary, " ;\n");
+ }
+ else return -1;
+ }
+
+ buf = table_get(r->subprocess_env,"CONTENT_LENGTH");
+ if(buf==NULL) return -1;
+
+ size = atoi(buf);
+ mb = (char *)palloc(r->pool,(size+1)*sizeof(char));
+
+ if(!mb ||
+ (setup_client_block(r ,REQUEST_CHUNKED_ERROR) != 0) ||
+ (should_client_block(r) == 0))
+ return -1;
+
+ hard_timeout("args.c copy script args", r);
+ handler = signal(SIGPIPE, SIG_IGN);
+
+ while(size-off > 0 && (len_read = get_client_block
+ (r, mb + off, size - off)) > 0) {
+ off += len_read;
+ }
+
+ signal(SIGPIPE, handler);
+ kill_timeout(r);
+
+ if(len_read < 0) return -1; // 讀的中途有中斷
+ mb[size]=0; // Ptt:截掉不需要吧 因為不是用字串處理方式
+ (*data) = mb;
+ return size;
+}
+
+#define ENCODED_NAME " name=\""
+#define ENCODED_FILENAME " filename=\""
+#define ENCODED_CONTENT "Content-Type: "
+
+//#define FILEDATAFILE DATABASEDIR "/" FDATA
+
+int
+unescape(request_rec *r, char** name, char** value) {
+ static char *sp=NULL, boundary[150];
+ static int fileupload, boundarylen, dsize;
+ pool *p = r->pool;
+ char ch, ch1, *dp, *p0, *p1, *temp_sp, *ftype;
+ int type;
+
+ if (sp==NULL) {
+ fileupload=0;
+ switch (r->method_number) {
+ case M_GET:
+ if (r->args) sp = pstrdup(p, r->args);
+ else {sp=NULL; return -1;}
+ break;
+ case M_POST:
+ if ((dsize =
+ inital_postdata(r, &fileupload, boundary,&sp))<0)
+ {sp=NULL; return -1; }
+ if(fileupload) boundarylen = strlen(boundary);
+ break;
+ default:
+ sp=NULL;
+ return -1;
+ }
+ }
+
+ if(fileupload)
+ {
+ if(dsize >0 && (temp_sp = memstr(sp, boundary, dsize)))
+ {
+ temp_sp += boundarylen;
+ p0 = strstr(temp_sp, "\r\n\r\n");
+ p1 = strstr(temp_sp, "\n\n");
+
+ if(!((*name) = strstr(temp_sp, ENCODED_NAME)))
+ {sp=NULL; return -1; }
+ (*name) += strlen(ENCODED_NAME);
+ strtok((*name) + 1 , "\"");
+ if( (!p0 && p1) || (p0 && p1 && p1<p0))
+ {
+ (*value) = sp = p1 + 2;
+ type = 2;
+ }
+ else if(p0)
+ {
+ (*value) = sp = p0 + 4;
+ type = 4;
+ }
+ else
+ {
+ sp=NULL;
+ return -1;
+ }
+
+ if((p1 = memstr(temp_sp, boundary, dsize - boundarylen)))
+ temp_sp = p1;
+ else
+ temp_sp = sp + dsize;
+
+ *(temp_sp - type) = 0;
+
+ // 檢查是不是file 若是就給fileinfo
+ if((dp=memstr(
+ (*name) + strlen(*name) +1, ENCODED_FILENAME, dsize)) &&
+ dp < *value)
+ {
+ dp += strlen(ENCODED_FILENAME);
+ p0 = strchr(dp,'"');
+ *p0 = 0;
+ if(p0 - dp>3)
+ {
+ fileheader_t *file=(fileheader_t *)pcalloc(p, sizeof(fileheader_t));
+ if((ftype = strstr(p0 + 1, ENCODED_CONTENT)))
+ {
+ ftype += strlen(ENCODED_CONTENT);
+ strtok(ftype, "\r\n");
+ }
+ while(p0 > dp && *p0 !='/' && *p0 !='\\') p0--;
+ strcpy(file->name, p0+1);
+ strcpy(file->content_type, ftype);
+ file->icontent_type = filetype(ftype);
+ // if(file->icontent_type & (FILE_TXT | FILE_HTML))
+ // file->size = strlen(sp);
+ // else
+ file->size = temp_sp - sp - type;
+ file->uploadtime = time(NULL);
+ file->data = (*value);
+ (*value) = (char *)file;
+ }
+ else
+ {
+ (*value) = NULL;
+ }
+ }
+
+ dsize -= (temp_sp - sp);
+ sp = temp_sp;
+ return 1;
+ }
+ else
+ {
+ sp=NULL;
+ return -1;
+ }
+ }
+
+ dp = (*name) = sp;
+ while(1) {
+ ch = *sp++;
+ switch(ch) {
+ case '+':
+ *dp++ = ' ';
+ break;
+ case '=':
+ *dp++ = '\0';
+ (*value) = dp;
+ break;
+ case '&': case '|':
+ *dp++ = '\0';
+ return 1;
+ case '\0': case EOF:
+ *dp = '\0';
+ sp=NULL;
+ return 0;
+ case '%':
+ ch = *sp++; ch1 = *sp++;
+ *dp++ = xtoc(ch, ch1);
+ break;
+ default:
+ *dp++=ch;
+ break;
+ }
+ }
+}
+
diff --git a/web/board.c b/web/board.c
new file mode 100644
index 00000000..43347912
--- /dev/null
+++ b/web/board.c
@@ -0,0 +1,39 @@
+#include "mod_ptt.h"
+
+extern int numboards;
+extern boardheader_t *bcache;
+extern int ptt_handler(request_rec *r, void *args);
+
+int bbs_board(request_rec *r, void *args)
+{
+ int i;
+ r->content_type = "text/xml";
+ ap_send_http_header(r);
+ ap_rputs("<hr> Ptt \n", r);
+return ptt_handler (r,args);
+
+ ap_rprintf(r,"r->filename : %s <br>",r->filename);
+ ap_rprintf(r,"r->request_time : %s <br>",ctime(&r->request_time));
+ ap_rprintf(r,"r->method : %s <br>",r->method);
+ ap_rprintf(r,"r->method_number : %d <br>",r->method_number);
+ ap_rprintf(r,"r->path_info : %s <br>",r->path_info);
+ ap_rprintf(r,"r->args : %s <br>",r->args);
+ ap_rprintf(r,"r->unparsed_uri : %s <br>",r->unparsed_uri);
+ ap_rprintf(r,"r->uri : %s <br>",r->uri);
+ ap_rprintf(r,"r->handler : %s <br>",r->handler);
+ ap_rprintf(r,"r->content_type : %s <br>",r->content_type);
+ ap_rprintf(r, "Server built: \"%s\"\n", ap_get_server_built());
+
+ ap_rputs("<hr> Ptt \n", r);
+
+ ap_rputs("<XML>",r);
+/*
+ for(i = 0; i++ < numboards; i++)
+ {
+ ap_rputs("<board>",r);
+ ap_rputs("</board>",r);
+ }
+*/
+
+ return OK;
+}
diff --git a/web/chmod b/web/chmod
new file mode 100644
index 00000000..a91df6d5
--- /dev/null
+++ b/web/chmod
@@ -0,0 +1 @@
+ftasfdsf
diff --git a/web/l b/web/l
new file mode 100755
index 00000000..5feafa93
--- /dev/null
+++ b/web/l
@@ -0,0 +1 @@
+lynx -dump ptt.cc/menu
diff --git a/web/mail.c b/web/mail.c
new file mode 100644
index 00000000..9f226afe
--- /dev/null
+++ b/web/mail.c
@@ -0,0 +1,6 @@
+#include "mod_ptt.h"
+
+int bbs_mail(request_rec *r, void *args)
+{
+ return OK;
+}
diff --git a/web/mod_ptt.c b/web/mod_ptt.c
new file mode 100644
index 00000000..3c4309ed
--- /dev/null
+++ b/web/mod_ptt.c
@@ -0,0 +1,284 @@
+#include "mod_ptt.h"
+extern SHM_t *SHM;
+extern int *GLOBALVAR;
+
+extern int numboards;
+extern boardheader_t *bcache;
+typedef struct excfg {
+ int cmode; /* Environment to which record applies (directory,
+ * server, or combination).
+ */
+#define CONFIG_MODE_SERVER 1
+#define CONFIG_MODE_DIRECTORY 2
+#define CONFIG_MODE_COMBO 3 /* Shouldn't ever happen. */
+ int local; /* Boolean: "Example" directive declared here? */
+ int congenital; /* Boolean: did we inherit an "Example"? */
+ char *trace; /* Pointer to trace string. */
+ char *loc; /* Location to which this record applies. */
+} excfg;
+
+static const char *trace = NULL;
+static table *static_calls_made = NULL;
+
+static pool *ptt_pool = NULL;
+static pool *ptt_subpool = NULL;
+
+
+module MODULE_VAR_EXPORT ptt_module;
+excfg * our_dconfig(request_rec *r)
+{
+
+ return (excfg *) ap_get_module_config(r->per_dir_config, &ptt_module);
+}
+
+static void setup_module_cells()
+{
+ if (ptt_pool == NULL) {
+ ptt_pool = ap_make_sub_pool(NULL);
+ };
+ if (static_calls_made == NULL) {
+ static_calls_made = ap_make_table(ptt_pool, 16);
+ };
+}
+
+
+static int xml_header(request_rec *r)
+{
+ r->content_type = "text/xml";
+ ap_send_http_header(r);
+ ap_rputs("<?xml version=\"1.0\" encoding=\"Big5\"?> \n", r);
+ ap_rprintf(r, "<!-- HTTP-Server-version=\"%s\"\n",
+ ap_get_server_version());
+ ap_rprintf(r," r-filename=\"%s\"\n",r->filename);
+ ap_rprintf(r," r-request_time=\"%s\"\n",ctime(&r->request_time));
+ ap_rprintf(r," r-method=\"%s\"\n",r->method);
+ ap_rprintf(r," r-method_number=\"%d\"\n",r->method_number);
+ ap_rprintf(r," r-path_info=\"%s\"\n",r->path_info);
+ ap_rprintf(r," r-args=\"%s\"\n",r->args);
+ ap_rprintf(r," r-unparsed_uri=\"%s\"\n",r->unparsed_uri);
+ ap_rprintf(r," r-handler=\"%s\"\n",r->handler);
+ ap_rprintf(r," r-content_type=\"%s\"\n",r->content_type);
+ ap_rprintf(r, " Serverbuilt=\"%s\" \n", ap_get_server_built());
+ ap_rprintf(r, " numboards=\"%d\" \n", numboards);
+ ap_rprintf(r, " shm=\"%d\" \n", SHM->loaded );
+ ap_rprintf(r, " max_user=\"%d\" -->", SHM->max_user );
+}
+static int userlist(request_rec *r)
+{
+ int i,offset=0;
+ userinfo_t *ptr;
+ xml_header(r);
+ if (r->header_only) {
+ return OK;
+ }
+ if(r->args) offset=atoi(r->args);
+ if(offset<0 || offset>SHM->UTMPnumber)offset=0;
+
+ ap_rprintf(r,"<userlist>");
+ for(i=offset;i<SHM->UTMPnumber && i<50+offset;i++)
+ {
+ ptr= (userinfo_t *)SHM->sorted[SHM->currsorted][0][i];
+ if(!ptr || ptr->userid[0]==0 || ptr->invisible ) continue;
+ ap_rprintf(r,"<user>\n");
+ ap_rprintf(r," <id>%d</id>\n",i+1);
+ ap_rprintf(r," <total>%d</total>\n",SHM->UTMPnumber);
+ ap_rprintf(r," <uid>%d</uid>\n",ptr->uid);
+ ap_rprintf(r," <userid>%s</userid>\n",ptr->userid);
+ ap_rprintf(r," <username>%s</username>\n",
+ ap_escape_html(r->pool,ptr->username));
+ ap_rprintf(r," <from>%s</from>\n",ptr->from);
+ ap_rprintf(r," <from_alias>%d</from_alias>\n",ptr->from_alias);
+ ap_rprintf(r," <mailalert>%d</mailalert>\n",ptr->mailalert);
+ ap_rprintf(r," <mind>%s</mind>\n",ap_escape_html(r->pool,ptr->mind));
+ ap_rprintf(r,"</user>");
+ }
+ ap_rprintf(r,"</userlist>");
+}
+static int showboard(request_rec *r, int id)
+{
+ int i;
+ boardheader_t *bptr=NULL;
+ id=id-1;
+ ap_rprintf(r,"<brdlist>");
+ bptr = (boardheader_t *)bcache[id].firstchild[0];
+ for(; bptr!= (boardheader_t*)~0; )
+ {
+ if((bcache[id].brdattr&BRD_HIDE)||
+ bcache[id].level&& !(bcache[id].brdattr & BRD_POSTMASK )) continue;
+ ap_rprintf(r,"<brd>\n");
+ i=(bptr-bcache);
+ ap_rprintf(r," <bid>%d</bid>",i+1);
+ ap_rprintf(r," <brdname>%s</brdname>\n",bptr->brdname);
+ ap_rprintf(r," <title>%s</title>\n",ap_escape_html(r->pool,bptr->title));
+ ap_rprintf(r," <nuser>%d</nuser>\n",bptr->nuser);
+ ap_rprintf(r," <gid>%d</gid>\n",bptr->gid);
+ ap_rprintf(r," <childcount>%d</childcount>\n",bptr->childcount);
+ ap_rprintf(r," <BM>%s</BM>\n",bptr->BM);
+ ap_rprintf(r," <brdattr>%d</brdattr>\n",bptr->brdattr);
+ ap_rprintf(r," <total>%d</total>\n",SHM->total[i]);
+ ap_rprintf(r,"</brd>\n");
+ bptr=(boardheader_t*)bptr->next[0];
+ }
+
+ ap_rprintf(r,"</brdlist>");
+}
+
+
+static int showpost(request_rec *r,int bid,int id, int num)
+{
+ int i;
+ num=256;
+ id=1;
+ char path[512];
+ fileheader_t headers[256];
+ memset(headers,0, sizeof(fileheader_t)*256);
+ sprintf(path,BBSHOME"/boards/%c/%s/.DIR",
+ bcache[bid-1].brdname[0],bcache[bid-1].brdname);
+ get_records(path, headers, sizeof(fileheader_t)*256, id,num);
+
+ ap_rprintf(r,"<postlist>");
+
+ for(i=0;i<256;i++)
+ {
+ ap_rprintf(r,"<post>\n");
+ ap_rprintf(r," <id>%d</id>",i+1);
+ ap_rprintf(r," <filename>%s</filename>\n",headers[i].filename);
+ ap_rprintf(r," <owner>%s</owner>\n",headers[i].owner);
+ ap_rprintf(r," <date>%s</date>\n",headers[i].date);
+ ap_rprintf(r," <title>%s</title>\n",
+ ap_escape_html(r->pool,headers[i].title));
+ ap_rprintf(r," <money>%d</money>\n",headers[i].money);
+ ap_rprintf(r," <filemode>%c</filemode>\n",headers[i].filemode);
+ ap_rprintf(r," <recommend>%d</recommend>\n",headers[i].recommend);
+ ap_rprintf(r,"</post>\n");
+ }
+ ap_rprintf(r,"</postlist>");
+}
+static int showmenujs(request_rec *r)
+{
+ int i;
+ boardheader_t *bptr;
+ r->content_type = "text/text";
+ ap_send_http_header(r);
+ ap_rputs("d=new dTree('d');\n",r);
+ ap_rputs("d.add(0,-1,'Class','');\n",r);
+ for(i=1;i<=numboards;i++)
+ {
+ bptr=&bcache[i-1];
+ if(!isalpha(bptr->brdname[0]))continue;
+
+ ap_rprintf(r,"d.add(%d,%d,\"%s %s..\",'/boards?%s');\n",
+ i,bptr->gid-1,
+ bptr->gid==1?"":bptr->brdname,
+ ap_escape_quotes(r->pool,
+ ap_escape_html(r->pool,bptr->title+7)),i);
+ }
+ ap_rputs("d.draw()\n",r);
+ return OK;
+}
+
+static int showxml(request_rec *r)
+{
+ int bid=1;
+ xml_header(r);
+ if (r->header_only) {
+ return OK;
+ }
+ if(r->args) bid=atoi(r->args);
+ if(bid<1 || bid>numboards)bid=1;
+
+ if(
+ !(bcache[bid-1].brdattr&BRD_HIDE)&&
+ !(bcache[bid-1].level&&!(bcache[bid-1].brdattr & BRD_POSTMASK)))
+ if( bid==1||bcache[bid-1].brdattr&BRD_GROUPBOARD)
+ showboard(r,bid);
+ else
+ showpost(r,bid,0,0);
+ return OK;
+}
+static int ptt_handler(request_rec *r)
+{
+ excfg *dcfg;
+
+ dcfg = our_dconfig(r);
+
+ ap_soft_timeout("send ptt call trace", r);
+
+ if(!strncmp(r->unparsed_uri,"/menu",5))
+ showmenujs(r);
+ else if(!strncmp(r->unparsed_uri,"/userlist",9))
+ userlist(r);
+ else
+ showxml(r);
+
+ ap_kill_timeout(r);
+ return OK;
+}
+
+/* OK Handler accepted the request and did its thing with it. */
+/* DECLINED Handler took no action. */
+/* HTTP_mumble Handler looked at request and found it wanting. */
+
+static void ptt_child_init(server_rec *s, pool *p)
+{
+
+ char *note;
+ char *sname = s->server_hostname;
+ attach_SHM();
+
+
+ setup_module_cells();
+ sname = (sname != NULL) ? sname : "";
+ note = ap_pstrcat(p, "ptt_child_init(", sname, ")", NULL);
+}
+
+static void ptt_child_exit(server_rec *s, pool *p)
+{
+
+ char *note;
+ char *sname = s->server_hostname;
+
+ /*
+ * The arbitrary text we add to our trace entry indicates for which server
+ * we're being called.
+ */
+ sname = (sname != NULL) ? sname : "";
+ note = ap_pstrcat(p, "ptt_child_exit(", sname, ")", NULL);
+}
+
+static const handler_rec ptt_handlers[] =
+{
+ {"ptt_h", ptt_handler},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT ptt_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* module initializer */
+ NULL, /* per-directory config creator */
+ NULL, /* dir config merger */
+ NULL, /* server config creator */
+ NULL, /* server config merger */
+ NULL, /* command table */
+ ptt_handlers, /* [9] list of handlers */
+ NULL, /* [2] filename-to-URI translation */
+ NULL, /* [5] check/validate user_id */
+ NULL, /* [6] check user_id is valid *here* */
+ NULL, /* [4] check access by host address */
+ NULL, /* [7] MIME type checker/setter */
+ NULL, /* [8] fixups */
+ NULL, /* [10] logger */
+#if MODULE_MAGIC_NUMBER >= 19970103
+ NULL, /* [3] header parser */
+#endif
+#if MODULE_MAGIC_NUMBER >= 19970719
+ ptt_child_init, /* process initializer */
+#endif
+#if MODULE_MAGIC_NUMBER >= 19970728
+ ptt_child_exit, /* process exit/cleanup */
+#endif
+#if MODULE_MAGIC_NUMBER >= 19970902
+ NULL
+#endif
+};
diff --git a/web/mod_ptt.h b/web/mod_ptt.h
new file mode 100644
index 00000000..125046d6
--- /dev/null
+++ b/web/mod_ptt.h
@@ -0,0 +1,13 @@
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "http_protocol.h"
+#include "util_script.h"
+#include "bbs.h"
+
+#include <stdio.h>
+
+
+#define PATHLEN 512
diff --git a/web/mytime.h b/web/mytime.h
new file mode 100755
index 00000000..c9e4f29d
--- /dev/null
+++ b/web/mytime.h
@@ -0,0 +1,189 @@
+/* Ptt : 常用函式整理 */
+
+/*
+ * 時間處理
+ */
+#include <time.h>
+#ifdef _BBS_UTIL
+ #undef pstrdup
+ #define pstrdup(p, str) strdup(str)
+#endif
+
+int
+mygetdate(time_t clock, int *year, int *mon, int *mday, int *week)
+{
+ struct tm *mytm = localtime(&clock);
+ if(year) *year = mytm->tm_year; /* 98 */
+ if(mon) *mon = mytm->tm_mon + 1; /* 1~12 */
+ if(mday) *mday = mytm->tm_mday; /* 1~31 */
+ if(week) *week = mytm->tm_wday; /* 0~6 */
+ return 0;
+}
+
+char *
+Cdatenum_slash(pool *p,time_t *clock) /* 98/04/21 */
+{
+ char foo[22];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 22, "%y/%m/%d", mytm);
+ return pstrdup(p, foo);
+}
+
+char *
+Cdatenum(pool *p,time_t *clock) /* 980421 */
+{
+ char foo[22];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 22, "%y%m%d", mytm);
+ return pstrdup(p, foo);
+}
+
+
+#ifndef _BBS_UTIL
+char *
+Cdatefullnum(pool *p,time_t *clock) /* 19980421 */
+{
+ char foo[22];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 22, "%Y%m%d", mytm);
+ return pstrdup(p, foo);
+}
+#else
+char *
+Cdatefullnum(char *p,time_t *clock) /* 19980421 */
+{
+ static char foo[22];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 22, "%Y%m%d", mytm);
+ return foo;
+}
+#endif
+
+char *
+Cdate(char *p,time_t *clock)
+{
+ char foo[22];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 22, "%D %T %a", mytm);
+ return pstrdup(p, foo);
+}
+
+char *
+Cdatelite(char *p,time_t *clock)
+{
+ char foo[18];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 18, "%D %T", mytm);
+ return pstrdup(p, foo);
+}
+
+char *
+whattime(char *p,time_t *clock)
+{
+ char foo[18];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 18, "%H:%M:%S", mytm);
+ return pstrdup(p, foo);
+}
+
+char *
+whatyear(char *p,time_t *clock)
+{
+ char foo[6];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 6, "%Y", mytm);
+ return pstrdup(p, foo);
+}
+
+char *
+whatmonth(char *p,time_t *clock)
+{
+ char foo[4];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 4, "%m", mytm);
+ return pstrdup(p, foo);
+}
+
+char *
+whatday(char *p,time_t *clock)
+{
+ char foo[4];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 4, "%d", mytm);
+ return pstrdup(p, foo);
+}
+
+char *
+C_week(pool *p, int a)
+{
+ char foo[5]="";
+ switch(a)
+ {
+ case 0:
+ case 7:
+ strcpy(foo,"日");
+ break;
+ case 1:
+ strcpy(foo,"一");
+ break;
+ case 2:
+ strcpy(foo,"二");
+ break;
+ case 3:
+ strcpy(foo,"三");
+ break;
+ case 4:
+ strcpy(foo,"四");
+ break;
+ case 5:
+ strcpy(foo,"五");
+ break;
+ case 6:
+ strcpy(foo,"六");
+ break;
+ }
+ return pstrdup(p, foo);
+}
+
+char *
+whatweek(char *p,time_t *clock)
+{
+ struct tm *mytm = localtime(clock);
+ return C_week(p, mytm->tm_wday);
+}
+
+char *
+whathour(char *p,time_t *clock)
+{
+ char foo[4]="";
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 6, "%H", mytm);
+ return pstrdup(p, foo);
+}
+
+char *
+whatminute(char *p,time_t *clock)
+{
+ char foo[4]="";
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 6, "%M", mytm);
+ return pstrdup(p, foo);
+}
+
+char *
+whatsecond(char *p,time_t *clock)
+{
+ char foo[4]="";
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 6, "%S", mytm);
+ return pstrdup(p, foo);
+}
+
+char *
+Wholetime(char *p,time_t *clock) /* 19980421 */
+{
+ char foo[40];
+ struct tm *mytm = localtime(clock);
+ strftime(foo, 40, "%Y年%m月%d日%H時%M分%S秒", mytm);
+ return pstrdup(p, foo);
+}
diff --git a/web/parse_html.c b/web/parse_html.c
new file mode 100755
index 00000000..402412de
--- /dev/null
+++ b/web/parse_html.c
@@ -0,0 +1,294 @@
+#include "mod_ptt.h"
+#include <time.h>
+#include <math.h>
+#define KUSERINFO "$userinfo$"
+#define KUSERID "$userid$"
+#define KUSERNAME "$username$"
+#define KUSERMONEY "$usermoney$"
+#define KTIMEYEAR "$timeyear$"
+#define KTIMEMONTH "$timemonth$"
+#define KTIMEMDAY "$timemday$"
+#define KTIMEWEEK "$timeweek$"
+#define KSERVERTIME "$servertime$"
+#define KTIMEHOUR "$hour$"
+#define KTIMEMINUTE "$minute$"
+#define KTIMESECOND "$second$"
+#define KMSGONLOAD "$MSGonLoad$"
+#define KFCSONLOAD "$FCSonLoad$"
+#define KHTMLTITLE "$HTMLtitle$"
+#define KSCROLLTITLE "$SCROLLtitle$"
+#define KBGCOLOR "$BGCOLOR$"
+#define KBGSOUND "$BGSOUND$"
+#define KINCHTML "$file:"
+
+
+
+char *
+ap_parseline(request_rec *r, const char *str, char *str_substiute[]) {
+ int i, off=0;
+ char *strbuf, *po;
+ pool *p = r->pool;
+ strbuf = pstrdup(p, str);
+
+ if(str_substiute == NULL) return strbuf;
+ for(i=0; str_substiute[i]!=NULL; i+=2)
+ {
+ off = 0;
+ while(po = strstr(strbuf + off, str_substiute[i]))
+ {
+ *po = 0;
+ strbuf = pstrcat(p, strbuf, str_substiute[i+1] !=NULL
+ ? str_substiute[i+1] : "", po+strlen(str_substiute[i]), NULL);
+ off += str_substiute[i+1] ? strlen(str_substiute[i+1]) : 0;
+ }
+ }
+ return strbuf;
+}
+
+char *
+ap_standard_parseline(request_rec *r, char *str)
+{
+ time_t now = time(NULL);
+ pool *p = r->pool;
+ char *str_substiute[]= // 關鍵字的代換表
+ {
+ KUSERID, "ptt",
+ KUSERNAME, "name",
+/*
+ KTIMEYEAR, whatyear(p,&now),
+ KTIMEMONTH,whatmonth(p,&now),
+ KTIMEMDAY, whatday(p,&now),
+ KTIMEWEEK, whatweek(p,&now),
+ KSERVERTIME, whattime(p,&now),
+ KTIMEHOUR, whathour(p,&now),
+ KTIMEMINUTE, whatminute(p,&now),
+ KTIMESECOND, whatsecond(p,&now),
+*/
+ KUSERINFO, NULL,
+ KUSERMONEY, "100",
+ NULL,NULL
+ };
+ return ap_parseline(r, str, str_substiute);
+}
+
+int
+ap_showfile(request_rec *r, char *filename, char *table[], char *t2[], FILE *fo)
+{
+ pool *p = r->pool;
+ FILE *fp = pfopen(p, filename, "r");
+ char *str, *incfile, buf[512];
+
+ if (!fp) {
+#if DEBUG
+ rputs(filename, r);
+#endif
+ return -1;
+ }
+
+ while (fgets(buf, 512, fp))
+ {
+
+ str = ap_standard_parseline(r,
+ ap_parseline(r,
+ ap_parseline(r, buf, table),
+ t2));
+
+ if ((incfile = strstr(str, KINCHTML)) != NULL) {
+ incfile += strlen(KINCHTML);
+ incfile = strtok(incfile, "$");
+#if 0
+ if (*incfile != '/')
+ incfile = ap_pstrcat(p, TEMPLATEDIR "/", incfile, NULL);
+#endif
+ ap_showfile(r, incfile, table, t2, fo);
+ } else if(fo) fputs(str, fo);
+ else rputs(str, r);
+ }
+
+ pfclose(p, fp);
+ return 0;
+}
+
+char *
+add_href(pool *p, char *l)
+{
+ char *href[] = {"http://", "ftp://", "gopher://", "file://",
+ "telnet://", "mailto:", NULL},
+ *end, url[PATHLEN], *tl, *po;
+ int i, urllen, off;
+
+ tl = pstrdup(p, l);
+
+ for(i=0; href[i]!=NULL; i++)
+ {
+ off = 0;
+ //Ptt: while 應該用 while 但 while 有bug
+ if((po = strstr(tl + off, href[i])))
+ {
+ for(end = po; (*end>='&' && *end<='z')||*end=='~' ; end++);
+ urllen = end - po;
+
+ if(urllen > PATHLEN)
+ {
+ off += PATHLEN; continue;
+ }
+
+ strncpy(url, po, urllen);
+ *po= 0;
+ url[urllen] = 0;
+ tl = psprintf(p, "%s<a href=\"%s\" target=\"%s\">%s</a>%s", tl,
+ url, "new", url, end);
+ off += 2 * urllen + 15;
+ }
+ }
+
+ return tl;
+}
+
+/*
+ format:
+ char *name, void *ptr, size_t length
+ char *name, int *ptr, -1
+ char *name, char **ptr, 0
+*/
+int
+GetQueryDatas(request_rec *r, int **table)
+{
+ int rc, i, match=0, dlen, maxlen;
+ char *name, *value, *str;
+ pool *p = r->pool;
+
+ for(i=1; table[i]!=NULL; i+=3)
+ {
+ if((int) table[i+1]) *table[i]=0;
+ else (char *) (*table[i]) = pstrdup(p, "");
+ }
+ do
+ {
+ if((rc = unescape(r, &name, &value))<0) break;
+ for(i=0; table[i]; i+=3)
+ {
+ if(!strcmp((char *)table[i], name)) break;
+
+#if 0
+/* SiE990313 test: 抓 未定義的變數 */
+ if(!strcmp((char *)table[i], "$SPARE$"))
+ {
+ (char *) (*table[i + 1]) = pstrdup(p, name);
+ continue;
+ }
+#endif
+ }
+ if(table[i] && table[i+1])
+ {
+ if((maxlen = (int) table[i+2]) > 0)
+ {
+ if(!*value) continue;
+ dlen = strlen((char *)table[i+1]);
+ str = ap_escape_html(p, value);
+ if(maxlen > dlen)
+ strexam(
+ strncat((char *)table[i+1],str,maxlen-dlen)
+ );
+ }
+ else if((int) table[i+2] == 0) // for file upload
+ {
+// str = ap_escape_html(p, value);
+ //if(value)
+ (*table[i+1]) = (int) value;
+// else (*table[i+1]) = (int) pstrdup(p,"");
+ }
+ else
+ {
+ if(!*value) continue;
+ *(table[i+1]) += atoi(value);
+ }
+ match++;
+ }
+ } while(rc>0);
+ return match;
+}
+
+
+int
+ap_url_redirect(request_rec *r, char *url)
+{
+ r->status = REDIRECT;
+
+ ap_table_setn(r->headers_out, "Location", pstrdup(r->pool, url));
+ return MOVED;
+ //return REDIRECT, MOVED 或 HTTP_SEE_OTHER 都可
+}
+
+char *
+pint2str(pool* p, int c)
+{
+ return ap_psprintf(p,"%d",c);
+}
+
+char*
+preplace(request_rec *r, char* src, char* sig, char* rep)
+{
+ char *ptr;
+ int siglen=strlen(sig), off=0;
+
+ while((ptr = strstr(src+off,sig)))
+ {
+ *ptr = 0;
+ src = pstrcat(r->pool, src, rep, NULL);
+ off = strlen(src);
+ src = pstrcat(r->pool, src, ptr+siglen, NULL);
+ }
+ return src;
+}
+
+int
+hex2dig(char *str)
+{
+ int base,ret=0,i,len=strlen(str);
+
+ for(i=0; i<len; i++)
+ {
+ if(str[i]>='a' && str[i]<='f') base = str[i]-'a'+10;
+ else if(str[i]>='A' && str[i]<='F') base = str[i]-'A'+10;
+ else if(str[i]>='0' && str[i]<='9') base = str[i]-'0';
+ else return -1;
+
+ ret += base*pow(16,len-i-1);
+ }
+ return ret;
+}
+
+char *
+pstrncpy(pool* p, char tmp[], int n)
+{
+ char *ptr;
+ ptr=pstrdup(p,tmp);
+ *(ptr+n)=0;
+ return psprintf(p,"%s",ptr);
+}
+
+char *
+GetPathToken(request_rec *r, int count)
+{
+ char *str, *token, *sepr = "/\\?&";
+ int i;
+ str = pstrdup(r->pool, r->path_info + 1);
+ token = strtok(str, sepr);
+ for( i = 1 ; i < count; i++)
+ {
+ token = strtok(NULL, sepr);
+ if(!token) return "-1"; /* Heat:count超過也要考慮 */
+ }
+ return token;
+}
+
+
+/*
+ 個人信件夾檔保管方式:
+
+ mail/@/rec/FF/F/UUDDTT
+ mail/@/dat/FF/F/UUDDTT
+
+*/
+
diff --git a/web/post.c b/web/post.c
new file mode 100644
index 00000000..3e67937e
--- /dev/null
+++ b/web/post.c
@@ -0,0 +1,6 @@
+#include "mod_ptt.h"
+
+int bbs_post(request_rec *r, void *args)
+{
+ return OK;
+}
diff --git a/web/r b/web/r
new file mode 100755
index 00000000..5e18e14c
--- /dev/null
+++ b/web/r
@@ -0,0 +1 @@
+sudo apachectl restart
diff --git a/web/s b/web/s
new file mode 100755
index 00000000..e1384f10
--- /dev/null
+++ b/web/s
@@ -0,0 +1 @@
+sudo apachectl stop
diff --git a/web/stuff.c b/web/stuff.c
new file mode 100755
index 00000000..b02dbb0d
--- /dev/null
+++ b/web/stuff.c
@@ -0,0 +1,269 @@
+/* Ptt : 常用字串函式整理 */
+#include "mod_ptt.h"
+
+// 缺少 escape_url的東西
+
+/*
+ * 檔案判別
+ */
+
+ /* 傳回:路徑大小 */
+
+off_t
+dashs(fname)
+ char *fname;
+{
+ struct stat st;
+
+ if (!stat(fname, &st))
+ return (st.st_size);
+ else
+ return 0; /* 無此檔是 size 0 */
+}
+
+ /* 傳回:路徑時間 */
+long
+dasht(char *fname)
+{
+ struct stat st;
+
+ if (!stat(fname, &st))
+ return (st.st_mtime);
+ else
+ return -1;
+}
+
+ /* 傳回:路徑是否為link檔 */
+int
+dashl(char *fname)
+{
+ struct stat st;
+ return (lstat(fname, &st) == 0 && S_ISLNK(st.st_mode));
+}
+
+ /* 傳回:路徑是否為檔案 */
+dashf(char *fname)
+{
+ struct stat st;
+
+ return (stat(fname, &st) == 0 && S_ISREG(st.st_mode));
+}
+
+/* 字串的小寫 */
+#define char_lower(c) ((c >= 'A' && c <= 'Z') ? c|32 : c)
+
+void
+str_lower(t, s)
+ char *t, *s;
+{
+ register char ch;
+ do
+ {
+ ch = *s++;
+ *t++ = char_lower(ch);
+ } while (ch);
+}
+
+int
+str_ncmp(s1, s2, n)
+ char *s1, *s2;
+ int n;
+{
+ int c1, c2;
+
+ while (n--)
+ {
+ c1 = *s1++;
+ if (c1 >= 'A' && c1 <= 'Z')
+ c1 |= 32;
+
+ c2 = *s2++;
+ if (c2 >= 'A' && c2 <= 'Z')
+ c2 |= 32;
+
+ if (c1 -= c2)
+ return (c1);
+
+ if (!c2)
+ break;
+ }
+ return 0;
+}
+char *
+memstr(char *mem, char *str, int size)
+{
+ char *loc, *ptr=mem, *end=mem+size;
+ int len = strlen(str);
+ while((loc = memchr(ptr, *str, size)))
+ {
+ if(!strncmp(loc, str, len))
+ return loc;
+ ptr = loc +1;
+ size = (end - ptr);
+ if(size <=0 ) return NULL;
+ }
+ return NULL;
+}
+
+/* 傳回: strstr的比較但不計大小寫的結果 */
+/*
+char *
+strcasestr(str, tag)
+ char *str, *tag;
+{
+ char buf[BUFLEN];
+
+ str_lower(buf, str);
+ return strstr(buf, tag);
+}
+*/
+
+/* 傳回: 一個checksum 給字串比較用 */
+
+int str_checksum(char *str)
+{
+ int n=1;
+ if(strlen(str) < 6) return 0;
+ while(*str)
+ n += *str++ ^ n;
+ return n;
+}
+
+int
+not_alpha(ch)
+ register char ch;
+{
+ return (ch < 'A' || (ch > 'Z' && ch < 'a') || ch > 'z');
+}
+
+int
+not_alnum(ch)
+ register char ch;
+{
+ return (ch < '0' || (ch > '9' && ch < 'A') ||
+ (ch > 'Z' && ch < 'a') || ch > 'z');
+}
+
+char
+ch2ph(char ch)
+{
+ static const
+ // a b c d e f g h i j k l m n o
+ char table[]={'2','2','2','3','3','3','4','4','4','5','5','5','6','6','6',
+ // p q r s t u v w x y z
+ '7','1','7','7','8','8','8','9','9','9','1'};
+ static char d;
+ d = char_lower(ch);
+ if(d>='a' && d<='z') d=table[d-'a'];
+ return d;
+}
+
+void
+archiv32(chrono, fname)
+ time_t chrono; /* 32 bits */
+ char *fname; /* 7 chars */
+{
+ char *str;
+ char radix32[32] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+ };
+
+ str = fname + 7;
+ *str = '\0';
+ for (;;)
+ {
+ *(--str) = radix32[chrono & 31];
+ if (str == fname)
+ return;
+ chrono >>= 5;
+ }
+}
+
+/* ARPANET時間格式 */
+char *
+Atime(clock)
+ time_t *clock;
+{
+ static char datemsg[40];
+ /* ARPANET format: Thu, 11 Feb 1999 06:00:37 +0800 (CST) */
+ /* strftime(datemsg, 40, "%a, %d %b %Y %T %Z", localtime(clock)); */
+ /* time zone的傳回值不知和ARPANET格式是否一樣,先硬給,同sendmail*/
+ strftime(datemsg, 40, "%a, %d %b %Y %T +0800 (CST)", localtime(clock));
+ return (datemsg);
+}
+
+
+/* userid是否合法 */
+int
+bad_user_id(userid)
+ char *userid;
+{
+ register char ch;
+ if (strlen(userid) < 2)
+ return 1;
+ if (not_alpha(*userid))
+ return 1;
+ if (!strcasecmp(userid, "new") || !strcasecmp(userid, "guest") ||
+ !strcasecmp(userid, "root") || !strcasecmp(userid, "webadm") ||
+ !strncasecmp(userid,"yam",3)
+ )
+ return 1;
+
+ while (ch = *(++userid))
+ {
+ if (not_alnum(ch) || ch == '0')
+ return 1;
+ }
+ return 0;
+}
+
+
+int
+logfile(pool *p, char *filename,char *buf)
+{
+ FILE *fp;
+ time_t now;
+ if( (fp = ap_pfopen(p, filename, "a" )) ) {
+
+ fputs( buf, fp );
+ if(!strchr(buf,'\n'))
+ {
+ now = time(NULL);
+ fputs(ctime(&now), fp);
+ }
+ ap_pfclose(p, fp );
+ return 0;
+ }
+ else{
+ printf("error open file");
+ return -1;
+ }
+}
+
+/* 檢查中文斷字問題 */
+char *strexam(char *s)
+{
+ int i;
+ int odd;
+ for (i = 0, odd = 0; s[i]; i++)
+ if (odd) odd = 0;
+ else if (s[i] & 128) odd = 1;
+ if (odd) s[--i] = 0;
+ return s;
+}
+
+int
+maxline(char *data,char *newline, int max)
+{
+ register int n, nlen=strlen(newline);
+ register char *po;
+
+ for(n=0, po = data; (po = strstr(po, newline)); po+=nlen)
+ {
+ if(++n>=max) {*po=0; return -1;}
+ }
+ return n;
+}
diff --git a/web/t b/web/t
new file mode 100755
index 00000000..6e8b84bc
--- /dev/null
+++ b/web/t
@@ -0,0 +1 @@
+tail /var/log/httpd-error.log
diff --git a/web/user.c b/web/user.c
new file mode 100644
index 00000000..fe5d0696
--- /dev/null
+++ b/web/user.c
@@ -0,0 +1,6 @@
+#include "mod_ptt.h"
+
+int bbs_user(request_rec *r, void *args)
+{
+ return OK;
+}