/******************************************************************* * 張貼文章 * * 佈告、信件 通用 * * return: WebRespondType *******************************************************************/ int PostArticle(char *pbuf, BOARDHEADER * board, POST_FILE * pf) { BOOL tonews = FALSE; char *p; unsigned char flag = 0x00; FILE *fp; int sign_num, URLParaType = request_rec->URLParaType; char fname[PATHLEN], post_path[PATHLEN], address[STRLEN], post_source[STRLEN], subject[STRLEN]; char buffer[STRLEN * 3]; if (URLParaType == PostSend || URLParaType == TreaSend) { if (PSCorrect == gLogin) /* guest */ { if (!strstr(_STR_BOARD_GUEST, board->filename)) return WEB_GUEST_NOT_ALLOW; else get_passwd(&curuser, username); } if ((curuser.userlevel < board->level)) { sprintf(WEBBBS_ERROR_MESSAGE, "%s 無權張貼文章於 %s 一般區<BR>理由: 使用者等級 < %d", username, board->filename, board->level); return WEB_ERROR; } if ((board->brdtype & BRD_IDENT) && (curuser.ident != 7)) { sprintf(WEBBBS_ERROR_MESSAGE, "%s 無權張貼文章於 %s 一般區<BR>理由: 未通過身份認證", username, board->filename); return WEB_ERROR; } #if 0 make_treasure_folder(direct, title, NULL) #endif /* treapost */ if (URLParaType == TreaSend) { if (!HAS_PERM(PERM_SYSOP) && strcmp(username, board->owner)) { sprintf(WEBBBS_ERROR_MESSAGE, "%s 無權張貼文章於 %s 精華區", username, board->filename); return WEB_ERROR; } settreafile(post_path, board->filename, pf->POST_NAME); } } else /* Send Mail */ {
/*********************************************************** * 轉寄文章檔案 * * 一般區、精華區、信件區通用 ************************************************************/ int ForwardArticle(char *pbuf, BOARDHEADER *board, POST_FILE *pf) { int result; char address[STRLEN], fname[PATHLEN]; strcpy(fname, pf->POST_NAME); if(request_rec->URLParaType == PostForward) setboardfile(pf->POST_NAME, board->filename, fname); else if(request_rec->URLParaType == TreaForward) settreafile(pf->POST_NAME, board->filename, fname); else if(request_rec->URLParaType == MailForward) setmailfile(pf->POST_NAME, username, fname); else return WEB_ERROR; GetPara2(address, "NUM", pbuf, 3, "-1"); pf->num = atoi(address); GetPara2(address, "ADDRESS", pbuf, STRLEN, ""); if((result = MailCheck(address)) != WEB_OK) return result; if(GetPostInfo(board, pf) != WEB_OK) { return WEB_FILE_NOT_FOUND; } if(!isfile(pf->POST_NAME)) { sprintf(WEBBBS_ERROR_MESSAGE, "開啟轉寄檔案失敗 %s", fname); return WEB_ERROR; } if(SendMail(-1, pf->POST_NAME, username, address, pf->fh.title, curuser.ident)) { strcpy(WEBBBS_ERROR_MESSAGE, "SendMail Error"); return WEB_ERROR; } #ifdef WEB_EVENT_LOG if(request_rec->URLParaType == MailForward) sprintf(log, "%s FROM=\"%s\" TO=\"%s\" SJT=\"%s\" UA=\"%s\"", POST_MailForward, username, address, pf->fh.title, request_rec->user_agent); else sprintf(log, "%s FROM=\"%s\" TO=\"%s\" SJT=\"%s\" UA=\"%s\"", POST_PostForward, username, address, pf->fh.title, request_rec->user_agent); #endif return WEB_OK_REDIRECT; }
/******************************************************************* * 根據 URLParaType 執行 POST 的要求 * * return HttpRespondType *******************************************************************/ static int DoPostRequest(REQUEST_REC * r, BOARDHEADER * board, POST_FILE * pf) { int result, URLParaType; char *form_data; result = WEB_ERROR; URLParaType = r->URLParaType; /* Get FORM data */ if ((form_data = GetFormBody(r->content_length, WEBBBS_ERROR_MESSAGE)) == NULL) return WEB_ERROR; #ifdef DEBUG weblog_line(server->debug_log, form_data); fflush(server->debug_log); #endif /* PostSend allow username&password in form body without login */ if (PSCorrect == nLogin && URLParaType == PostSend) { char pass[PASSLEN * 3]; GetPara2(username, "Name", form_data, sizeof(username), ""); /* get userdata from form */ GetPara2(pass, "Password", form_data, sizeof(pass), ""); Convert(pass, FALSE); xstrncpy(password, pass, sizeof(password)); PSCorrect = CheckUserPassword(username, password); } if (URLParaType == PostSend || URLParaType == TreaSend || URLParaType == PostEdit || URLParaType == TreaEdit || URLParaType == PostForward || URLParaType == TreaForward || URLParaType == PostDelete || URLParaType == TreaDelete || URLParaType == SkinModify || URLParaType == AclModify || URLParaType == AclMail ) { int perm; /* board->filename should set in advance, now in ParseURI() */ if (get_board(board, board->filename) <= 0 || board->filename[0] == '\0') return WEB_BOARD_NOT_FOUND; if ((perm = boardCheckPerm(board, &curuser, request_rec)) != WEB_OK) return perm; } if (PSCorrect == Correct || (PSCorrect == gLogin && (URLParaType == PostSend || URLParaType == TreaSend)) || URLParaType == UserNew) { switch (URLParaType) { case PostSend: case TreaSend: if (URLParaType == TreaSend) { char post_path[PATHLEN]; settreafile(post_path, board->filename, pf->POST_NAME); result = PostArticle(form_data, board, post_path); } else result = PostArticle(form_data, board, NULL); if (result) { #if 1 if (URLParaType == TreaSend) { if (strlen(pf->POST_NAME)) sprintf(skin_file->filename, "/%streasure/%s/%s/$", BBS_SUBDIR, board->filename, pf->POST_NAME); else sprintf(skin_file->filename, "/%streasure/%s/$", BBS_SUBDIR, board->filename); } else { sprintf(skin_file->filename, "/%sboards/%s/", BBS_SUBDIR, board->filename); } #endif if (PSCorrect == Correct) UpdateUserRec(URLParaType, &curuser, board); } break; case MailSend: case AclMail: if ((result = PostArticle(form_data, board, NULL))) { sprintf(skin_file->filename, "/%smail/", BBS_SUBDIR); UpdateUserRec(URLParaType, &curuser, NULL); } break; case PostEdit: case TreaEdit: if ((result = EditArticle(form_data, board, pf))) { sprintf(skin_file->filename, "/%s%s.html", BBS_SUBDIR, pf->POST_NAME); } break; case PostForward: case TreaForward: case MailForward: if ((result = ForwardArticle(form_data, board, pf))) { int start, end; char path[PATHLEN]; find_list_range(&start, &end, pf->num, DEFAULT_PAGE_SIZE, pf->total_rec); setdotfile(path, pf->POST_NAME, NULL); sprintf(skin_file->filename, "/%s%s%d-%d", BBS_SUBDIR, path, start, end); } break; case PostDelete: case TreaDelete: case MailDelete: result = DeleteArticle(form_data, board, pf); if (URLParaType == PostDelete) { int start, end; find_list_range(&start, &end, pf->num, DEFAULT_PAGE_SIZE, pf->total_rec); sprintf(skin_file->filename, "/%sboards/%s/%d-%d", BBS_SUBDIR, board->filename, start, end); } else if (URLParaType == TreaDelete) { char path[PATHLEN]; setdotfile(path, pf->POST_NAME, NULL); sprintf(skin_file->filename, "/%s%s", BBS_SUBDIR, path); } else /* MailDelete */ { sprintf(skin_file->filename, "/%smail/", BBS_SUBDIR); } break; case UserNew: if ((result = NewUser(form_data, &curuser))) setfile(HTML_UserNewOK); break; #if 0 case UserIdent: if ((result = DoUserIdent(form_data, &curuser))) setfile(HTML_UserIdentOK); break; #endif case UserData: if ((result = UpdateUserData(form_data, &curuser))) sprintf(skin_file->filename, "/%susers/%s", BBS_SUBDIR, HTML_UserData); break; case UserPlan: if ((result = UpdateUserPlan(form_data, &curuser))) sprintf(skin_file->filename, "/%susers/%s", BBS_SUBDIR, HTML_UserPlan); break; case UserSign: if ((result = UpdateUserSign(form_data, &curuser))) sprintf(skin_file->filename, "/%susers/%s", BBS_SUBDIR, HTML_UserSign); break; case UserFriend: if ((result = UpdateUserFriend(form_data, &curuser))) sprintf(skin_file->filename, "/%susers/%s", BBS_SUBDIR, HTML_UserFriend); break; #ifdef WEB_ADMIN case BoardModify: /* admin function */ if (!HAS_PERM(PERM_SYSOP) #ifdef NSYSUBBS || !strstr(request_rec->fromhost, "140.117.12.") #endif ) { sprintf(WEBBBS_ERROR_MESSAGE, "%s 沒有權限修改看板設定", username); result = WEB_ERROR; } else if ((result = ModifyBoard(form_data, board))) sprintf(skin_file->filename, "/%sboards/%s/%s", BBS_SUBDIR, board->filename, HTML_BoardModify); break; #endif case SkinModify: /* customize board skins */ if (strcmp(username, board->owner) && !HAS_PERM(PERM_SYSOP)) { sprintf(WEBBBS_ERROR_MESSAGE, "%s 沒有權限修改討論區介面", username); result = WEB_ERROR; } else if (!(board->brdtype & BRD_WEBSKIN)) { sprintf(WEBBBS_ERROR_MESSAGE, "討論區 [%s] 尚未打開自定介面功\能", board->filename); result = WEB_ERROR; } else if ((result = ModifySkin(form_data, board, pf))) setfile(HTML_SkinModifyOK); break; case AclModify: if (strcmp(username, board->owner) && !HAS_PERM(PERM_SYSOP)) { sprintf(WEBBBS_ERROR_MESSAGE, "%s 沒有權限修改板友名單", username); result = WEB_ERROR; } else if (!(board->brdtype & BRD_ACL)) { sprintf(WEBBBS_ERROR_MESSAGE, "討論區 [%s] 尚未啟用 Access 限制功\能", board->filename); result = WEB_ERROR; }
/******************************************************************* * 從 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; } }