精華區beta SetupBBS 關於我們 聯絡資訊
/*-------------------------------------------------------*/ /* more.c ( NTHU CS MapleBBS Ver 2.36 ) */ /*-------------------------------------------------------*/ /* target : simple & beautiful ANSI/Chinese browser */ /* create : 95/03/29 */ /* update : 95/12/15 */ /*-------------------------------------------------------*/ #include "bbs.h" #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define MAXPATHLEN 256 static char *more_help[] = { "\0閱\讀文章功\能鍵使用說明", "\01游標移動功\能鍵", "(↑) 上捲一行", "(↓)(Enter) 下捲一行", "(^B)(PgUp)(BackSpace) 上捲一頁", "(→)(PgDn)(Space) 下捲一頁", "(0)(g)(Home) 檔案開頭", "($)(G) (End) 檔案結尾", "\01其他功\能鍵", "(/) 搜尋字串", "(n/N) 重複正/反向搜尋", "(TAB) URL連結", "(Ctrl-T) 存到暫存檔", "(:/f/b) 跳至某頁/下/上篇", "(F/B) 跳至同一搜尋主題下/上篇", "(a/A) 跳至同一作者下/上篇", "([/]) 主題式閱\讀 上/下", "(t) 主題式循序閱\讀", "(Ctrl-C) 小計算機", "(q)(←) 結束", "(h)(H)(?) 輔助說明畫面", NULL}; int beep = 0; static int readln(fp, buf) FILE *fp; char *buf; { register int ch, i, len, bytes, in_ansi; len = bytes = in_ansi = i = 0; while (len < 80 && i < ANSILINELEN && (ch = getc(fp)) != EOF) { bytes++; if (ch == '\n') { break; } else if (ch == '\t') { do { buf[i++] = ' '; } while ((++len & 7) && len < 80); } else if (ch == '\a') { beep = 1; } else if (ch == '\033') { if (showansi) buf[i++] = ch; in_ansi = 1; } else if (in_ansi) { if (showansi) buf[i++] = ch; if (!strchr("[0123456789;,", ch)) in_ansi = 0; } else if (isprint2(ch)) { len++; buf[i++] = ch; } } buf[i] = '\0'; return bytes; } int more(fpath, promptend) char *fpath; int promptend; { extern char* strcasestr(); static char *head[4] = {"作者", "標題", "時間" ,"轉信"}; char *ptr, *word, buf[256],*ch1; struct stat st; FILE *fp; usint pagebreak[MAXPAGES], pageno, lino; int line, ch, viewed, pos, numbytes; int header = 0; int local = 0; char search_char0=0; static char search_str[81]=""; typedef char* (*FPTR)(); static FPTR fptr; int searching = 0; int scrollup = 0; char *printcolor[3]= {"44","33;45","0;34;46"}, color =0; char *http[80]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; /* Ptt */ char pagemode = 0; char pagecount = 0; memset(pagebreak, 0, sizeof(pagebreak)); if (*search_str) search_char0 = *search_str; *search_str = 0; if (!(fp = fopen(fpath, "r"))) return -1; if (fstat(fileno(fp), &st)) return -1; pagebreak[0] = pageno = viewed = line = pos = 0; clear(); while ((numbytes = readln(fp, buf)) || (line == t_lines)) { if (scrollup) { rscroll(); move(0, 0); } if (numbytes) /* 一般資料處理 */ { if (!viewed) /* begin of file */ { if (showansi) /* header processing */ { if (!strncmp(buf, str_author1, LEN_AUTHOR1)) { line = 3; word = buf + LEN_AUTHOR1; local = 1; } else if (!strncmp(buf, str_author2, LEN_AUTHOR2)) { line = 4; word = buf + LEN_AUTHOR2; } while (pos < line) { if (!pos && ((ptr = strstr(word, str_post1)) || (ptr = strstr(word, str_post2)))) { ptr[-1] = '\0'; prints(" %s %-53.53s %.4s %-13s\n", head[0], word, ptr, ptr + 5); } else if (pos < 4) prints(" %s %-72.72s\n", head[pos], word); viewed += numbytes; numbytes = readln(fp, buf); if(!pos && viewed >= 79) /* 第一行太長了 */ { if (memcmp( buf, head[1], 2)) /* 第二行不是 [標....] */ { viewed += numbytes; /* 讀下一行進來處理 */ numbytes = readln(fp, buf); } } pos++; } if (pos) { header = 1; prints("%s\n", msg_seperator); line = pos = 4; } } lino = pos; word = NULL; } /* ※處理引用者 & 引言 */ if ((buf[1] == ' ') && (buf[0] == ':' || buf[0] == '>')) word = ""; else if ((buf[0] == 'ꄧ && buf[1] == '뀧) || !strncmp(buf, "==>", 3)) word = ""; ch1 = buf ; while(1) /* Ptt */ { int i; char e,*ch2; if(ch2 = strstr(ch1,"http://")); else if(ch2 = strstr(ch1,"gopher://")); else if(ch2 = strstr(ch1,"mailto:")); else break; for(e=0; ch2[e] != ' ' && ch2[e] != '\n' && ch2[e] != '\0' && ch2[e] != '"' && ch2[e] != ';' && ch2[e] != ']'; e++); for(i=0;http[i] && i<80;i++) if(!strncmp(http[i],ch2,e) && http[e]==0) break; if(!http[i]) { http[i] = (char *) malloc( e+1 ); strncpy(http[i],ch2,e); http[i][e]=0; pagecount++; } ch1 = &ch2[7]; } if (word) outs(word); { /* woju */ char msg[500], *pos; if (*search_str && (pos = fptr(buf, search_str))) { char SearchStr[81]; char buf1[100], *pos1; strncpy(SearchStr, pos, strlen(search_str)); SearchStr[strlen(search_str)] = 0; searching = 0; sprintf(msg, "%.*s%s", pos - buf, buf, SearchStr); while (pos = fptr(pos1 = pos + strlen(search_str), search_str)) { sprintf(buf1, "%.*s%s", pos - pos1, pos1, SearchStr); strcat(msg, buf1); } strcat(msg, pos1); outs(Ptt_prints(msg)); } else { outs(Ptt_prints(buf)); } } if (word) { outs(""); word = NULL; } outch('\n'); if (beep) { bell(); beep = 0; } if (line < b_lines) /* 一般資料讀取 */ line++; if (line == b_lines && searching == -1) { if (pageno > 0) fseek(fp, viewed = pagebreak[--pageno], SEEK_SET); else searching = 0; lino = pos = line = 0; clear(); continue; } if (scrollup) { move(line = b_lines, 0); clrtoeol(); for (pos = 1; pos < b_lines; pos++) viewed += readln(fp, buf); } else if (pos == b_lines) /* 捲動螢幕 */ scroll(); else pos++; if (!scrollup && ++lino >= b_lines && pageno < MAXPAGES - 1) { pagebreak[++pageno] = viewed; lino = 1; } if (scrollup) { lino = scrollup; scrollup = 0; } viewed += numbytes; /* 累計讀過資料 */ } else line = b_lines; /* end of END */ if (promptend && (!searching && line == b_lines || viewed == st.st_size)) { /* Kaede 剛好 100% 時不停 */ /* if (viewed == st.st_size && viewed - numbytes == pagebreak[1]) continue; */ move(b_lines, 0); if (viewed == st.st_size) { if (searching == 1) searching = 0; color = 0; } else if (pageno == 1 && lino == 1) { if (searching == -1) searching = 0; color = 1; } else color = 2; prints("m 瀏覽 P.%d(%d%%) m %-30.30s%s", printcolor[color],pageno,(viewed * 100) / st.st_size, pagemode ? "30;47": "31;47", pagemode ? http[pagemode-1] : "(h)求助 →↓[PgUp][", pagemode ? "[TAB]切換 [Enter]選定 放棄" :"PgDn][Home][End]游標移動 ←[q]結束 "); while (line == b_lines || (line > 0 && viewed == st.st_size)) { switch (ch = egetch()) { case ':': { char buf[10]; int i = 0; getdata(b_lines - 1, 0, "Goto Page: ", buf, 5, DOECHO); sscanf(buf, "%d", &i); if (0 < i && i < MAXPAGES && (i == 1 || pagebreak[i - 1])) pageno = i - 1; else if (pageno) pageno--; lino = line = 0; break; } case '/': { char ans[4] = "n"; *search_str = search_char0; getdata_buf(b_lines - 1, 0,"[搜尋]關鍵字:", search_str, 40, DOECHO); if (*search_str) { searching = 1; if (getdata(b_lines - 1, 0, "區分大小寫(Y/N/Q)? [N] ", ans, 4, LCECHO) && *ans == 'y') fptr = strstr; else fptr = strcasestr; } if (*ans == 'q') searching = 0; if (pageno) pageno--; lino = line = 0; break; } case 'n': if (*search_str) { searching = 1; if (pageno) pageno--; lino = line = 0; } break; case 'N': if (*search_str) { searching = -1; if (pageno) pageno--; lino = line = 0; } break; case 'r': case 'R': case 'Y': fclose(fp); return 7; case 'y': fclose(fp); return 8; case 'A': fclose(fp); return 9; case 'a': fclose(fp); return 10; case 'F': fclose(fp); return 11; case 'B': fclose(fp); return 12; case KEY_LEFT: if(pagemode) { pagemode = 0; *search_str = 0; if (pageno) pageno--; lino = line = 0; break; } fclose(fp); return 6; case 'q': fclose(fp); return 0; case 'b': fclose(fp); return 1; case 'f': fclose(fp); return 3; case ']': /* Kaede 為了主題閱讀方便 */ fclose(fp); return 4; case '[': /* Kaede 為了主題閱讀方便 */ fclose(fp); return 2; case '=': /* Kaede 為了主題閱讀方便 */ fclose(fp); return 5; case Ctrl('F'): case KEY_PGDN: line = 1; break; case 't': if (viewed == st.st_size) { fclose(fp); return 4; } line = 1; break; case ' ': if (viewed == st.st_size) { fclose(fp); return 3; } line = 1; break; case KEY_RIGHT: if (viewed == st.st_size) { fclose(fp); return 0; } line = 1; break; case '\r': case '\n': if (pagemode){ more_web(http[pagemode-1],YEA); /*pagebreak[0] = pageno = viewed = line = pos = 0;*/ pagemode = 0; *search_str = 0; if (pageno) pageno--; lino = line = 0; break; } case KEY_DOWN: if (viewed == st.st_size || promptend == 2 && (ch == '\r' || ch == '\n')) { fclose(fp); return 3; } line = t_lines - 2; break; case '$': case 'G': case KEY_END: line = t_lines; break; case '0': case 'g': case KEY_HOME: pageno = line = 0; break; case 'h': case 'H': case '?': /* Kaede Buggy ... */ show_help(more_help); if (pageno) pageno--; lino = line = 0; break; case 'E': if (strcmp(fpath, "etc/ve.hlp")) { fclose(fp); vedit(fpath, HAS_PERM(PERM_SYSOP) ? 0 : 2); return 0; } break; case Ctrl('R'): if (currutmp->msgs[0].last_pid) { show_last_call_in(); my_write(currutmp->msgs[0].last_pid, "水球丟回去:"); if (pageno) pageno--; lino = line = 0; } break; case KEY_ESC: if (KEY_ESC_arg == 'n') { edit_note(); if (pageno) pageno--; lino = line = 0; } else if (KEY_ESC_arg == 'c') capture_screen(); break; case Ctrl('U'): t_users(); if (pageno) pageno--; lino = line = 0; break; case Ctrl('C'): cal(); if (pageno) pageno--; lino = line = 0; break; case Ctrl('T'): getdata(b_lines - 2, 0, "把這篇文章收入到暫存檔?[y/N] ", buf, 4, LCECHO); if(buf[0] == 'y' ) { char tmpbuf[128]; setuserfile(tmpbuf, ask_tmpbuf(b_lines - 1)); sprintf(buf,"cp -f %s %s",fpath, tmpbuf); system(buf); } if (pageno) pageno--; lino = line = 0; break; /* case Ctrl('T'): x_cdict(); if (pageno) pageno--; lino = line = 0; break;*/ case Ctrl('I'): /* t_idle(); if (pageno) pageno--; lino = line = 0; */ if(!pagecount) break; pagemode = (pagemode % pagecount) + 1; /* if(pagemode!=1) searching =1; else searching =-1;*/ strncpy(search_str,http[pagemode-1],80); search_str[80] =0; fptr = strstr; if (pageno) pageno--; lino = line = 0; break; case KEY_UP: line = -1; break; case Ctrl('B'): case KEY_PGUP: if (pageno > 1) { if (lino < 2) pageno -= 2; else pageno--; lino = line = 0; } else if (pageno && lino > 1) pageno = line = 0; break; case Ctrl('H'): if (pageno > 1) { if (lino < 2) pageno -= 2; else pageno--; lino = line = 0; } else if (pageno && lino > 1) pageno = line = 0; /* woju */ else { fclose(fp); return 1; } } } if (line > 0) { move(b_lines, 0); clrtoeol(); refresh(); } else if (line < 0) { /* Line scroll up */ if (pageno <= 1) { if (lino == 1 || !pageno) { fclose(fp); return 1; } if (header && lino <= 5) { fseek(fp, viewed = pagebreak[scrollup = lino = pageno = 0] = 0, SEEK_SET); clear(); } } if (pageno && lino > 1 + local) { line = (lino - 2) - local; if (pageno > 1 && viewed == st.st_size) line += local; scrollup = lino - 1; fseek(fp, viewed = pagebreak[pageno - 1], SEEK_SET); while (line--) viewed += readln(fp, buf); } else if (pageno > 1) { scrollup = b_lines - 1; line = (b_lines - 2) - local; fseek(fp, viewed = pagebreak[--pageno - 1], SEEK_SET); while (line--) viewed += readln(fp, buf); } line = pos = 0; } else { pos = 0; fseek(fp, viewed = pagebreak[pageno], SEEK_SET); move(0,0); clear(); } } } fclose(fp); if (promptend) { pressanykey(); clear(); } else outs(reset_color); return 0; } int more_web(fpath, promptend) char *fpath; int promptend; { int a; FILE *fp; struct hostent *h; char *ch,*ch1; char *hostname = fpath,userfile[MAXPATHLEN],file[MAXPATHLEN]="/"; struct sockaddr_in sin; char genbuf[200]; time_t dtime; int i; if(ch=strstr(fpath,"mailto:")) { if(!HAS_PERM(PERM_LOGINOK)) { move(b_lines - 1,0); outs(" 您的權限不足無法使用internet mail... "); refresh(); sleep(1); return 0; } if(!invalidaddr(&ch[7]) && getdata(b_lines - 1, 0, "[寄信]主題:", genbuf, 40, DOECHO)) { do_send(&ch[7], genbuf); } else { move(b_lines - 1,0); outs(" 收信人email 或 標題 有誤... "); refresh(); sleep(1); } return 0; } if(ch=strstr(fpath,"gopher://")) { ITEM item; strcpy(item.X.G.server, &ch[9]); strcpy(item.X.G.path, "1/"); item.X.G.port = 70; gem(fpath , &item, 0); return 0; } if(ch=strstr(fpath,"http://")) { hostname=&ch[7]; } if(ch=strchr(hostname,'/')) { *ch=0; if(&ch1[1]) strcat(file,&ch[1]); } if(file[strlen(file)-1] == '/') { strcat(file,"index.html"); } move(b_lines-1,0); clrtoeol(); #ifdef USE_PROXY sprintf(genbuf," 正在連往%s.(proxy:%s).....請稍候...." ,hostname,PROXYSERVER); #else sprintf(genbuf," 正在連往%s......請稍候....",hostname); #endif outs(genbuf); refresh(); #ifdef LOCAL_PROXY /* 先找 local disk 的 proxy */ time(&dtime); sprintf(userfile,"hproxy/%s%s",hostname,file); if(dashf(userfile) && (dtime - dasht(userfile)) < HPROXYDAY * 24 * 60 && more(userfile,promptend)) { return 1; } ch=userfile - 1; while(ch1 = strchr(ch + 1,'/')) { *ch1 = 0; if(!dashd(ch)) mkdir(ch+1,0755); chdir(ch+1); *ch1 = '/'; ch = ch1; } chdir(BBSHOME); #endif #ifndef USE_LYNX #ifdef USE_PROXY if (!(h = gethostbyname(PROXYSERVER))) { outs(" 找不到這個proxy server!.."); refresh(); sleep(1); return; } (void) memset((char *) &sin, 0, sizeof(sin)); sin.sin_family = AF_INET; if (h == NULL) sin.sin_addr.s_addr = inet_addr(PROXYSERVER); else (void) memcpy(&sin.sin_addr.s_addr, h->h_addr, h->h_length); sin.sin_port = htons((ushort)PROXYPORT); /* HTTP port */ a = socket(AF_INET, SOCK_STREAM, 0); if ((connect(a, (struct sockaddr *) & sin, sizeof sin)) < 0) { outs(" 連接到proxy受到拒絕 ! "); refresh(); sleep(1); return; } sprintf(genbuf,"GET http://%s/%s HTTP/1.1\n",hostname,file); #else if (!(h = gethostbyname(hostname))) { outs(" 找不到這個server!.."); refresh(); sleep(1); return; } (void) memset((char *) &sin, 0, sizeof(sin)); sin.sin_family = AF_INET; if (h == NULL) sin.sin_addr.s_addr = inet_addr(hostname); else (void) memcpy(&sin.sin_addr.s_addr, h->h_addr, h->h_length); sin.sin_port = htons((ushort)80); a = socket(AF_INET, SOCK_STREAM, 0); if ((connect(a, (struct sockaddr *) & sin, sizeof sin)) < 0) { outs(" 連接受到拒絕 ! "); refresh(); sleep(1); return; } sprintf(genbuf,"GET %s\n",file); #endif for(i=strlen(file); file[i-1] != '/' && i>0 ; i-- ); file[i] = 0; i=strlen(genbuf); (void) write(a,genbuf,i); #define BLANK 001 #define ISPRINT 002 #define PRE 004 #define CENTER 010 if(fp = fopen(userfile,"w")); { int flag=2,c; char path[256]; unsigned char j,k; while(i =read(a,genbuf,200)) { if (i<0) return; genbuf[i]=0; for(j=0,k=0;genbuf[j] && j<i;j++) { if((flag & ISPRINT) && genbuf[j] == '<' ) { flag |= BLANK; } else if((flag & ISPRINT) && genbuf[j] == '>' ) flag &= ~BLANK; else { if(!(flag & BLANK)) { if(j!=k && (genbuf[j] != '\n' || flag & PRE)) genbuf[k++] = genbuf[j]; } else { switch(char_lower(genbuf[j])) { case 'a': /* strstr(&genbuf[j],"http */ break; case 'b': if(genbuf[j+1]=='r' && genbuf[j+2]=='>') genbuf[k++] = '\n'; break; case 'h': if(genbuf[j+1]=='r' && (genbuf[j+2]=='>' || genbuf[j+2]=='s')) { strncpy(&genbuf[k],"\n--\n",4); k+=4; } break; case 'l': if(genbuf[j+1]=='i' && genbuf[j+2]=='>') { strncpy(&genbuf[k],"\n◎ ",4); k+=4; } break; case 'p': if(genbuf[j+1]=='>') { genbuf[k++] = '\n'; genbuf[k++] = '\n'; } else if(genbuf[j+1]=='r' && genbuf[j+2]=='e') { flag ^= PRE; } break; case 't': if(genbuf[j+1]=='d' && genbuf[j+2]=='>') { strncpy(&genbuf[k],"\n-\n",3); k+=3; } break; } } if( (genbuf[j] & 0x80) && (flag & ISPRINT)) flag &= ~ISPRINT; else flag |= ISPRINT; } } genbuf[k]=0; fputs(genbuf,fp); } fclose(fp); close(a); return more(userfile,promptend); } return 0; #else /* use lynx dump */ sprintf(genbuf,"lynx -dump http://%s%s > %s",hostname,file,userfile); system(genbuf); return more(userfile,promptend); #endif }