/******************************************************************* * FileName: 要送出去的檔案名稱 * * 如果是圖形或是其他類型檔案直接送出 * 如果是 HTML 形式檔案則分析出 tag 將其代入適當的資料 *******************************************************************/ int ShowFile(SKIN_FILE *sf) { FILE *fp; int cache_idx; char type[STRLEN], tag[512]; char pbuf[HTTP_REQUEST_LINE_BUF]; #if 0 fprintf(fp_out, "ShowFile=%s", sf->filename); fflush(fp_out); #endif if (sf->mime_type > 1) /* 不是HTML, 不用處理 WEBBBS tag, 直接送出去 */ { if((cache_idx = CacheState(sf->filename, NULL)) == -1 || difftime(file_shm[cache_idx].file.mtime, sf->mtime) != 0) cache_idx = do_cache_file(sf->filename); if(cache_idx != -1) /* file is cached */ { file_shm[cache_idx].atime = request_rec->atime; file_shm[cache_idx].hit++; write(STDOUT_FILENO, file_shm[cache_idx].data, file_shm[cache_idx].file.size); } else { int size; if((fp = fopen(sf->filename, "rb")) == NULL) return FALSE; while((size = fread(pbuf, 1, sizeof(pbuf), fp)) != 0 ) fwrite(pbuf, 1, size, fp_out); fclose(fp); } } else /* html file, should process it */ { if((cache_idx = CacheState(sf->filename, NULL)) == -1 || difftime(html_shm[cache_idx].file.mtime, sf->mtime) != 0) cache_idx = do_cache_html(sf->filename); #if 0 fprintf(fp_out, "cache_idx = %d", cache_idx); fflush(fp_out); #endif if(cache_idx != -1) /* file is cached */ { int i; html_shm[cache_idx].atime = request_rec->atime; html_shm[cache_idx].hit++; for(i=0; html_shm[cache_idx].format[i].type; i++) { if(html_shm[cache_idx].format[i].type == 'S') { fwrite(html_shm[cache_idx].data+html_shm[cache_idx].format[i].offset, sizeof(char), (html_shm[cache_idx].format[i+1].offset)-(html_shm[cache_idx].format[i].offset), fp_out); } else { xstrncpy(pbuf, html_shm[cache_idx].data+html_shm[cache_idx].format[i].offset, (html_shm[cache_idx].format[i+1].offset)-(html_shm[cache_idx].format[i].offset)+1); GetBBSTag(type, tag, pbuf); DoTagCommand(type, tag); } } } else { char *p, *data, *next; if ((fp = fopen(sf->filename, "r")) == NULL) return FALSE; while (fgets(pbuf, sizeof(pbuf), fp) != NULL) { if ((p = strchr(pbuf, '\n')) != NULL) *p = '\0'; data = pbuf; while(1) /* process WEBBBS TAG */ { if((next = GetBBSTag(type, tag, data)) != NULL) { fprintf(fp_out, "%s", data); data = next; DoTagCommand(type, tag); } else { fprintf(fp_out, "%s\n", data); break; } } } fclose(fp); } } return TRUE; }
/******************************************************************* * 根據 URLParaType 執行 GET 的要求 * * * return WebRespondType *******************************************************************/ int DoGetRequest(REQUEST_REC * rc, BOARDHEADER * board, POST_FILE * pf) { char *p, *boardname; int URLParaType = rc->URLParaType; char fname[PATHLEN]; boardname = board->filename; if (URLParaType == Redirect) { /* redirect target must set in ParseURI() */ return WEB_REDIRECT; } if (PSCorrect != Correct && (URLParaType == MailList || URLParaType == MailRead || URLParaType == SkinModify)) { return WEB_USER_NOT_LOGIN; } if (URLParaType == PostList || URLParaType == PostRead || URLParaType == TreaList || URLParaType == TreaRead || URLParaType == SkinModify || URLParaType == Board) { int perm; if (get_board(board, boardname) <= 0 || board->filename[0] == '\0') return WEB_BOARD_NOT_FOUND; if ((perm = CheckBoardPerm(board, &curuser)) != WEB_OK) return perm; if (board->brdtype & BRD_WEBSKIN) /* Board has custom html skin */ { char *skin, web_board_dir[PATHLEN]; if (URLParaType == SkinModify) { if (strlen(pf->POST_NAME) != 0) { xstrncpy(web_board_dir, pf->POST_NAME, PATHLEN); skin = strrchr(web_board_dir, '/') + 1; setskinfile(pf->POST_NAME, boardname, skin); } } else if (!strstr(skin_file->filename, HTML_BoardModify)) { /* set specfic skin file to custom file */ xstrncpy(web_board_dir, skin_file->filename, PATHLEN); skin = strrchr(web_board_dir, '/') + 1; setskinfile(skin_file->filename, boardname, skin); } } else { if (strstr(skin_file->filename, HTML_SkinModify)) return WEB_FILE_NOT_FOUND; } } if (strstr(skin_file->filename, HTML_BoardModify) && (!HAS_PERM(PERM_SYSOP) || PSCorrect != Correct)) { return WEB_FILE_NOT_FOUND; } switch (URLParaType) { case TreaRead: case PostRead: if (GetPostInfo(board, pf) != WEB_OK) return WEB_FILE_NOT_FOUND; break; case TreaList: case PostList: pf->total_rec = get_num_records(pf->POST_NAME, FH_SIZE); break; case MailList: if (PSCorrect == Correct) pf->total_rec = get_num_records(pf->POST_NAME, FH_SIZE); else pf->total_rec = 0; break; case MailRead: if (PSCorrect == Correct) { int RESULT = GetPostInfo(board, pf); if (RESULT != WEB_OK) return RESULT; } break; case UserList: case BoardList: case TreaBoardList: case UserData: case SkinModify: /* do nothing here.. */ break; case UserQuery: /* put USER_REC in curuser for query */ if (!get_passwd(&curuser, username)) { bzero(&curuser, sizeof(USEREC)); return WEB_USER_NOT_FOUND; } break; case Board: /* cuscom webboard */ case Mail: /* ?? */ #if 0 fprintf(fp_out, "DoGetRequest Board,Mail:[%s]", skin_file->filename); fflush(fp_out); #endif if (CacheState(skin_file->filename, NULL) < 0 && !isfile(skin_file->filename)) { return WEB_FILE_NOT_FOUND; } break; default: #if 0 fprintf(fp_out, "DoGetRequest default:[%s]\r\n", skin_file->filename); fflush(fp_out); #endif xstrncpy(fname, skin_file->filename, sizeof(fname)); if (isBadURI(fname)) { BBS_SUBDIR[0] = 0x00; return WEB_BAD_REQUEST; } sprintf(skin_file->filename, "%s%s", HTML_PATH, fname + 1); if (CacheState(skin_file->filename, NULL) == -1) /* file not in cache */ { if (isdir(skin_file->filename)) { p = skin_file->filename + strlen(skin_file->filename) - 1; if (*p == '/') { strcat(skin_file->filename, DEFAULT_HTML); } else { sprintf(skin_file->filename, "%s/", fname); return WEB_REDIRECT; } } else { if ((p = strrchr(fname + 1, '/')) == NULL) p = fname; if (!strcmp(p, "/boards") || !strcmp(p, "/treasure") || !strcmp(p, "/mail") || !strcmp(p, "/users")) { sprintf(skin_file->filename, "%s/", fname); return WEB_REDIRECT; } } if (!isfile(skin_file->filename)) { BBS_SUBDIR[0] = 0x00; return WEB_FILE_NOT_FOUND; } } #ifdef WEB_LOGIN_CHECK return WebLoginCheck(); #endif } return WEB_OK; }
/******************************************************************* * 從 URI 判斷要求及抓出有用的資訊 * set BOARDNAME, POST_NAME, SKIN_FILE * * return URLParaType *******************************************************************/ int ParseURI(const char *curi, REQUEST_REC *r, BOARDHEADER *board, POST_FILE *pf) { char *p, *boardname; int HttpRequestType; char skin[PATHLEN], post[PATHLEN]; *skin = 0x00; *post = 0x00; *BBS_SUBDIR = 0x00; boardname = board->filename; HttpRequestType = r->HttpRequestType; if(curi[strlen(curi)-1] == '\\') { strncat(skin_file->filename, curi, strlen(curi)-1); return Redirect; } else if((p = strstr(curi, "/treasure/")) != NULL) { /* subdir/treasure/bname/ subdir/treasure/bname/start-end subdir/treasure/bname/treadir/treapost */ xstrncpy(BBS_SUBDIR, curi+1, p-curi+1); curi = p + 10; #if 0 if(curi[strlen(curi)-1] == '\\') { sprintf(skin_file->filename, "/%streasure/", BBS_SUBDIR); strncat(skin_file->filename, curi, strlen(curi)-1); return Redirect; } #endif GetURIToken(boardname, post, skin, curi); #if 0 fprintf(fp_out, "[BOARDNAME=%s, post=%s, skin=%s]<br>", boardname, post, skin); fflush(fp_out); #endif if(HttpRequestType == POST) { xstrncpy(pf->POST_NAME, post, PATHLEN); if(!strcmp(skin, POST_PostSend)) return TreaSend; else if(!strcmp(skin, POST_PostEdit)) return TreaEdit; else if(!strcmp(skin, POST_PostForward)) return TreaForward; else if(!strcmp(skin, POST_PostDelete)) return TreaDelete; else return Board; } if(strlen(boardname)==0) /* no BOARDNAME assigned , list all boards */ { if(strlen(skin)==0) { sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_TreaBoardList); return TreaBoardList; } else { /* skin is boardname */ sprintf(skin_file->filename, "/%streasure/%s/", BBS_SUBDIR, skin); return Redirect; } } if(strlen(skin)==0) /* must be treasure dir */ { if(strlen(post)==0) { settreafile(pf->POST_NAME, board->filename, DIR_REC); } else { settreafile(pf->POST_NAME, board->filename, post); strcat(pf->POST_NAME, "/"); strcat(pf->POST_NAME, DIR_REC); } sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_TreaList); return TreaList; } if(strlen(post)) /* has treasure sub-dir*/ { settreafile(pf->POST_NAME, boardname, post); strcat(pf->POST_NAME, "/"); strcat(pf->POST_NAME, skin); } else { settreafile(pf->POST_NAME, boardname, skin); } if(isPost(skin)) { strip_html(pf->POST_NAME); sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_TreaPost); return TreaRead; } if(isdir(pf->POST_NAME)) /* check isdir before isPost */ { sprintf(skin_file->filename, "/%s%s/", BBS_SUBDIR, pf->POST_NAME); return Redirect; } sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, skin); if(CacheState(skin_file->filename, NULL) >=0 || isfile(skin_file->filename)) { if(strlen(post)==0) return TreaList; settreafile(pf->POST_NAME, board->filename, post); return TreaRead; } if(isList(skin, &(pf->list_start), &(pf->list_end))) { if(strlen(post)==0) settreafile(pf->POST_NAME, board->filename, DIR_REC); else sprintf(pf->POST_NAME, "treasure/%s/%s/%s", boardname, post, DIR_REC); sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_TreaList); return TreaList; } else { settreafile(skin_file->filename, boardname, skin); return Board; } } else if((p = strstr(curi, "/boards/")) != NULL) { /* subdir/board/bname/ subdir/board/bname/start-end subdir/board/bname/post */ xstrncpy(BBS_SUBDIR, curi+1, p-curi+1); curi = p + 8; GetURIToken(boardname, post, skin, curi); #if 0 fprintf(fp_out, "[BOARDNAME=%s, post=%s, skin=%s]<br>", boardname, post, skin); fflush(fp_out); #endif if(HttpRequestType == POST) { xstrncpy(pf->POST_NAME, post, PATHLEN); if(!strcmp(skin, POST_PostSend)) return PostSend; else if(!strcmp(skin, POST_PostEdit)) return PostEdit; else if(!strcmp(skin, POST_PostForward)) return PostForward; else if(!strcmp(skin, POST_PostDelete)) return PostDelete; else if(!strcmp(skin, POST_BoardModify)) return BoardModify; else if(!strcmp(skin, POST_SkinModify)) return SkinModify; else if(!strcmp(skin, POST_AccessListModify)) return AccessListModify; else return Board; } if(strlen(boardname)==0) { /* case: /boards/ /boards/boardname */ if(strlen(skin)==0) { sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_BoardList); return BoardList; } else { /* skin is boardname */ sprintf(skin_file->filename, "/%sboards/%s/", BBS_SUBDIR, skin); return Redirect; } } if(strlen(skin)==0) { /* case: /boards/boardname/ */ sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_PostList); setboardfile(pf->POST_NAME, boardname, DIR_REC); return PostList; } if(isList(skin, &(pf->list_start), &(pf->list_end))) { setboardfile(pf->POST_NAME, board->filename, DIR_REC); sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_PostList); return PostList; } if(isPost(skin)) { strip_html(skin); setboardfile(pf->POST_NAME, boardname, skin); sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_Post); return PostRead; } sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, skin); if(CacheState(skin_file->filename, NULL) >=0 || isfile(skin_file->filename)) { if(strlen(post)==0) /* is DIR_REC skin */ { if(!strcmp(skin, HTML_SkinModify)) { *(pf->POST_NAME) = '\0'; return SkinModify; } else { setboardfile(pf->POST_NAME, boardname, DIR_REC); return PostList; } } else /* is post skin */ { sprintf(pf->POST_NAME, "%s%s%s", HTML_PATH, BBS_SUBDIR, post); if(isfile(pf->POST_NAME)) { sprintf(pf->POST_NAME, "%s%s%s", HTML_PATH, BBS_SUBDIR, post); return SkinModify; } else { setboardfile(pf->POST_NAME, board->filename, post); return PostRead; } } } setboardfile(skin_file->filename, boardname, skin); return Board; } else if((p = strstr(curi, "/mail/")) != NULL) { xstrncpy(BBS_SUBDIR, curi+1, p-curi+1); curi = p + 6; GetURIToken(boardname, post, skin, curi); #if 0 fprintf(fp_out, "[BOARDNAME=%s, post=%s, skin=%s]<br>", boardname, post, skin); fflush(fp_out); #endif if(HttpRequestType == POST) { xstrncpy(pf->POST_NAME, boardname, PATHLEN); if(!strcmp(skin, POST_MailSend)) return MailSend; else if(!strcmp(skin, POST_MailForward)) return MailForward; else if(!strcmp(skin, POST_MailDelete)) return MailDelete; else return OtherFile; } /* !! 'BOARDNAME' is 'post' in this section !! */ #if 0 if(strlen(boardname)==0 && strlen(skin)==0) { sprintf(skin_file->filename, "%s%s", BBS_SUBDIR, HTML_MailList); setmailfile(pf->POST_NAME, username, DIR_REC); return MailList; } #endif if(strlen(skin)==0) { sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_MailList); setmailfile(pf->POST_NAME, username, DIR_REC); return MailList; } if(isList(skin, &(pf->list_start), &(pf->list_end))) { setmailfile(pf->POST_NAME, username, DIR_REC); sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_MailList); return MailList; } if(isPost(skin)) { strip_html(skin); setmailfile(pf->POST_NAME, username, skin); sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_Mail); return MailRead; } sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, skin); if(CacheState(skin_file->filename, NULL) >=0 || isfile(skin_file->filename)) { if(strlen(board->filename) != 0) { setmailfile(pf->POST_NAME, username, boardname); return MailRead; } else { setmailfile(pf->POST_NAME, username, DIR_REC); return MailList; } } setmailfile(skin_file->filename, username, skin); return Mail; } else if((p = strstr(curi, "/users/")) != NULL) { xstrncpy(BBS_SUBDIR, curi+1, p-curi+1); curi = p + 7; GetURIToken(board->filename, post, skin, curi); #if 0 fprintf(fp_out, "[BOARDNAME=%s, post=%s, skin=%s]", board->filename, post, skin); fflush(fp_out); #endif if(HttpRequestType == POST) { if(!strcmp(skin, POST_UserNew)) return UserNew; else if(!strcmp(skin, POST_UserIdent)) return UserIdent; else if(!strcmp(skin, POST_UserData)) return UserData; else if(!strcmp(skin, POST_UserPlan)) return UserPlan; else if(!strcmp(skin, POST_UserSign)) return UserSign; else if(!strcmp(skin, POST_UserFriend)) return UserFriend; else return OtherFile; } if(strlen(skin)==0) { if(strlen(board->filename)!=0) { xstrncpy(username, board->filename, IDLEN); sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_UserQuery); return UserQuery; } else { sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_UserList); return UserList; } } if(isList(skin, &(pf->list_start), &(pf->list_end))) { sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_UserList); return UserList; } sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, skin); if(CacheState(skin_file->filename, NULL) >=0 || isfile(skin_file->filename)) return UserData; xstrncpy(username, skin, IDLEN); sprintf(skin_file->filename, "%s%s%s", HTML_PATH, BBS_SUBDIR, HTML_UserQuery); return UserQuery; } else if(!strncmp(curi, "/~", 2)) /* want user planfile only */ { curi+=2; #if 0 fprintf(fp_out, "userplan name=%s ", curi); fflush(fp_out); #endif xstrncpy(username, curi, IDLEN); strtok(username, " /\t\r\n"); sprintf(skin_file->filename, "%s%s", HTML_PATH, HTML_UserPlanShow); return UserQuery; } else { #if 0 fprintf(fp_out, "[other file=%s]", curi); fflush(fp_out); #endif #ifdef NSYSUBBS /* for compatiable with old URL parameter ================== */ if((p = strstr(curi, "BoardName=")) != NULL || (p = strstr(curi, "boardname=")) != NULL) { p+=10; strtok(p, "?&/"); sprintf(skin_file->filename, "/txtVersion/boards/%s/", p); return Redirect; } /* ========================================================= */ #endif xstrncpy(skin_file->filename, curi, PATHLEN); xstrncpy(BBS_SUBDIR, curi+1, PATHLEN); if((p = strrchr(BBS_SUBDIR, '/')) != NULL) *(p+1) = 0x00; else BBS_SUBDIR[0] = 0x00; return OtherFile; } }