phpbbs.wforum.c
来自「linux/unix环境下的建站系统」· C语言 代码 · 共 826 行 · 第 1/2 页
C
826 行
#include "php_kbs_bbs.h" #ifdef HAVE_WFORUM/* add by roy 2003.8.7 struct wwwthreadheader *//* used for .WWWTHREAD */struct wwwthreadheader{ struct fileheader origin; /* groupid */ struct fileheader lastreply; /* id for last article */ unsigned int articlecount; /* number of articles */ unsigned int flags; unsigned int unused; /* used for further index */};#define FILE_ON_TOP 0x2 /* on top mode *//* generates .WEBTHREAD */// balance is LH (left heavy), EH (even), RH (right heavy)enum balance { LH, EH, RH };typedef struct _wwwthread_treenode { struct wwwthreadheader content; // what's written into .WEBTHREAD finally /* AVL Tree supportive variables. This is used for quickly searching groupid. */ enum balance bf; // bf is the balance factor struct _wwwthread_treenode *Lchild; struct _wwwthread_treenode *Rchild; /* linked list supportive variables. This linked list is sorted by lastreply.posttime, so can be written into .WEBTHREAD linearly */ struct _wwwthread_treenode *previous;} wwwthread_treenode;/* following four routines are standard AVL operation support. */static wwwthread_treenode *AVL_RotateLeft(wwwthread_treenode * p){ wwwthread_treenode *temp; temp = p->Rchild; p->Rchild = temp->Lchild; temp->Lchild = p; p = temp; return p;}static wwwthread_treenode *AVL_RotateRight(wwwthread_treenode * p){ wwwthread_treenode *temp; temp = p->Lchild; p->Lchild = temp->Rchild; temp->Rchild = p; p = temp; return p;}static wwwthread_treenode *AVL_RightBalance(wwwthread_treenode * r){ wwwthread_treenode *x; wwwthread_treenode *w; x = r->Rchild; switch (x->bf) { case RH: r->bf = EH; x->bf = EH; r = AVL_RotateLeft(r); break; case LH: w = x->Lchild; switch (w->bf) { case EH: r->bf = EH; x->bf = EH; break; case LH: r->bf = EH; x->bf = RH; break; case RH: r->bf = LH; x->bf = EH; break; } w->bf = EH; x = AVL_RotateRight(x); r->Rchild = x; r = AVL_RotateLeft(r); break; default: break; } return r;}static wwwthread_treenode *AVL_LeftBalance(wwwthread_treenode * r){ wwwthread_treenode *x; wwwthread_treenode *w; x = r->Lchild; switch (x->bf) { case LH: r->bf = EH; x->bf = EH; r = AVL_RotateRight(r); break; case RH: w = x->Rchild; switch (w->bf) { case EH: r->bf = EH; x->bf = EH; break; case RH: r->bf = EH; x->bf = LH; break; case LH: r->bf = RH; x->bf = EH; break; } w->bf = EH; x = AVL_RotateLeft(x); r->Lchild = x; r = AVL_RotateRight(r); break; default: break; } return r;}/* * insert a node into the AVL Tree. * * @param proot *proot is the place to store the current root node, can be changed if the tree is rotated after insertion * @param fh *fh is the fileheader information to be stored in content field. * @param flags newly created node->content.flags * @param previous *previous is the place to store the previous node in the linked list. If the groupid is already in the AVL * tree, then no node is created and *previous leaves unchanged; if a node is newly created, *previous stores * the newly created node address * * @author atppp */static bool AVL_Insert(wwwthread_treenode ** proot, struct fileheader *fh, int flags, wwwthread_treenode** previous){ bool tallersubtree; bool taller = false; wwwthread_treenode *root; int cmp; root = *proot; if (root == NULL) { root = (wwwthread_treenode *) malloc(sizeof(wwwthread_treenode)); if (root == NULL) { *previous = NULL; return false; } root->content.lastreply = *fh; /* * here is the trick: if this post is not the original post, set origin.groupid to something else. * So later when written into the .WEBTHREAD file, we know whether the original post does exist or not. */ if (fh->id == fh->groupid) root->content.origin = *fh; else root->content.origin.groupid = fh->groupid + 1; root->content.flags = flags; root->content.articlecount = 1; root->content.unused = 0; root->previous = *previous; //linked list support *previous = root; //return the newly created node address in *previous, so the caller can set tail variable. /* AVL Tree support */ root->Lchild = NULL; root->Rchild = NULL; root->bf = EH; taller = true; } else { cmp = fh->groupid - root->content.lastreply.groupid; if (cmp < 0) { tallersubtree = AVL_Insert(&(root->Lchild), fh, flags, previous); if (tallersubtree) switch (root->bf) { case LH: root = AVL_LeftBalance(root); taller = false; break; case EH: root->bf = LH; taller = true; break; case RH: root->bf = EH; taller = false; break; } else taller = false; } else if (cmp > 0) { tallersubtree = AVL_Insert(&(root->Rchild), fh, flags, previous); if (tallersubtree) switch (root->bf) { case LH: root->bf = EH; taller = false; break; case EH: root->bf = RH; taller = true; break; case RH: root = AVL_RightBalance(root); taller = false; } else taller = false; } else { // the groupid (node) already exists /* We have a bug here: sysmail board won't generate correct .WEBTHREAD file. But who cares!!! */ if (root->content.lastreply.groupid == root->content.lastreply.id) { // this node was created by Zhiding fileheader root->content.lastreply = *fh; } else { root->content.articlecount++; if ((fh->groupid == fh->id) && (root->content.flags != FILE_ON_TOP)) { //found the original post, put into origin field /* 后面这个判断只是为了保证新旧代码产生 .WEBTHREAD 完全一致。这个细节以后还要调整 */ root->content.origin =*fh; } } taller = false; } } *proot = root; return taller;}static void clearWWWThreadList(wwwthread_treenode *p){ wwwthread_treenode *q; while (p!=NULL) { q=p->previous; free(p); p=q; }}static int www_generateOriginIndex(const char* board)/* added by roy 2003.7.17 generate .WEBTHREAD index file. Modified by atppp 2004.06.03 */{ struct fileheader *ptr1; struct flock ldata, ldata2; int fd, fd2, size, total, i; char olddirect[PATHLEN]; char currdirect[PATHLEN]; char *ptr; struct stat buf; /* AVL Tree support */ wwwthread_treenode *root = NULL; /* linked list support */ wwwthread_treenode *tail = NULL; wwwthread_treenode *temp = NULL; int bid; struct BoardStatus* bs; setbdir(DIR_MODE_NORMAL, olddirect, board); setbdir(DIR_MODE_WEB_THREAD, currdirect, board); if ((fd = open(currdirect, O_WRONLY | O_CREAT | O_TRUNC, 0664)) == -1) { bbslog("user", "%s", "recopen err"); return -1; /* 创建文件发生错误*/ } ldata.l_type = F_WRLCK; ldata.l_whence = 0; ldata.l_len = 0; ldata.l_start = 0; if (fcntl(fd, F_SETLKW, &ldata) == -1) { bbslog("user", "%s", "reclock err"); close(fd); return -2; /* lock error*/ } /* 开始互斥过程*/ if ((fd2 = open(olddirect, O_RDONLY, 0664)) == -1) { bbslog("user", "%s", "recopen err"); ldata.l_type = F_UNLCK; fcntl(fd, F_SETLKW, &ldata); close(fd); return -3; } ldata2.l_type = F_RDLCK; ldata2.l_whence = 0; ldata2.l_len = 0; ldata2.l_start = 0; if (fcntl(fd2, F_SETLKW, &ldata2) == -1) { bbslog("user", "%s", "reclock err"); ldata.l_type = F_UNLCK; fcntl(fd, F_SETLKW, &ldata); close(fd); close(fd2); return -4; /* lock error*/ } if (fstat(fd2, &buf)==-1) { ldata2.l_type = F_UNLCK; fcntl(fd2, F_SETLKW, &ldata2); close(fd2); ldata.l_type = F_UNLCK; fcntl(fd, F_SETLKW, &ldata); close(fd); return -5; } total = buf.st_size /sizeof(fileheader); if ((i = safe_mmapfile_handle(fd2, PROT_READ, MAP_SHARED, &ptr, &buf.st_size)) != 1) { if (i == 2) end_mmapfile((void *) ptr, buf.st_size, -1); ldata2.l_type = F_UNLCK; fcntl(fd2, F_SETLKW, &ldata2); close(fd2); ldata.l_type = F_UNLCK; fcntl(fd, F_SETLKW, &ldata); close(fd); return -5; } size=sizeof(struct wwwthreadheader); bid = getbid(board,NULL); bs = getbstatus(bid); for (i=bs->toptitle-1;i>=0;i--) { if (bs->topfh[i].groupid!=bs->topfh[i].id) continue; AVL_Insert(&root, &(bs->topfh[i]), FILE_ON_TOP, &temp); if (temp == NULL) { //malloc failure, impossible? clearWWWThreadList(tail); return -5; } tail = temp; } ptr1 = (struct fileheader *) ptr; for (i=total-1;i>=0;i--) { AVL_Insert(&root, &(ptr1[i]), 0, &temp); if (temp == NULL) { //malloc failure, impossible? clearWWWThreadList(tail); return -5; } tail = temp; } while (tail!=NULL) { temp=tail->previous; if (tail->content.origin.groupid != tail->content.lastreply.groupid) { //original post does not exist, do something tail->content.origin = tail->content.lastreply; tail->content.origin.id = tail->content.origin.groupid; tail->content.origin.groupid++; //indication that this thread has no original post. } write(fd,&(tail->content),size); free(tail); tail=temp; } end_mmapfile((void *) ptr, buf.st_size, -1); ldata2.l_type = F_UNLCK; fcntl(fd2, F_SETLKW, &ldata2); close(fd2); ldata.l_type = F_UNLCK; fcntl(fd, F_SETLKW, &ldata); /* 退出互斥区域*/ close(fd); return 0;}static int cmp_original_date(const void *a, const void *b) { struct wwwthreadheader * pa; struct wwwthreadheader * pb; pa = *((struct wwwthreadheader **)a); pb = *((struct wwwthreadheader **)b); return get_posttime(&(pb->origin)) - get_posttime(&(pa->origin));}PHP_FUNCTION(bbs_searchtitle){ char *board,*title, *title2, *title3,*author; int bLen,tLen,tLen2,tLen3,aLen; long date,mmode,attach,maxreturn; /* date < 0 search for threads whose original post time is within (-date) days. - atppp 20040727 */ const struct boardheader *bh; char dirpath[STRLEN]; int fd;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?