int getbnum_safe(const char *bname, session_t *session, const int mode) { register int i; for (i = 0; i < brdshm->numboards; i++) if ((((mode == 1) && check_read_perm(session->currentuser,&bcache[i]))) || ((mode == 2) && check_see_perm(session -> currentuser, &bcache[i]))) if (!strncasecmp(bname, bcache[i].filename, STRLEN)) return i + 1; return 0; }
int fill_super_board(struct userec* user,const char *searchname, int result[], int max) { register int i; int total=0; for (i = 0; i < brdshm->numboards && total < max ; i++) { if (bcache[i].filename[0] == '\0') continue; if (check_read_perm(user, &bcache[i])) { if (strcasestr(bcache[i].filename, searchname) || strcasestr(bcache[i].des, searchname) || strcasestr(bcache[i].title, searchname)) { result[total] = i + 1; total ++; } } } return total; }
/* return .-delimited manageable bid list */ int get_manageable_bids(struct userec *user, char *buf, int buflen) { register int i; int total=0; char *bufptr = buf; buf[0] = '\0'; for (i = 0; i < brdshm->numboards; i++) { if (bcache[i].filename[0] == '\0') continue; if (check_read_perm(user, &bcache[i])) { if (chk_BM_instr(bcache[i].BM, user->userid)) { total++; sprintf(bufptr, "%d.", i+1); bufptr += strlen(bufptr); if (bufptr - buf > buflen - 10) break; } } } if (total) *(bufptr-1) = '\0'; return total; }
static inline int process_article(const struct fileheader *f,int n,const struct boardheader *b){ static const struct flock lck_set={.l_type=F_RDLCK,.l_whence=SEEK_SET,.l_start=0,.l_len=0,.l_pid=0}; static const struct flock lck_clr={.l_type=F_UNLCK,.l_whence=SEEK_SET,.l_start=0,.l_len=0,.l_pid=0}; static struct stat st; static struct tm *p; static char name[BOUND]; static int fd,i,j,k,l; static time_t timestamp; static const char *S,*M,*N; static void *vp; do{ if((timestamp=get_posttime(f))<from||timestamp>to) break; if(ISSET(PARAM_P)&&strcmp(f->owner,post)) break; setbfile(name,b->filename,f->filename); if(stat(name,&st)==-1||!S_ISREG(st.st_mode)||st.st_size<size) break; if((fd=open(name,O_RDONLY #ifdef O_NOATIME |O_NOATIME #endif /* O_NOATIME */ ,0644))==-1) break; if(fcntl(fd,F_SETLKW,&lck_set)==-1){ close(fd); break; } vp=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,fd,0); fcntl(fd,F_SETLKW,&lck_clr); close(fd); if((S=(const char*)vp)==MAP_FAILED) break; for(p=NULL,j=0,i=0;S[i]&&i<st.st_size;i++){ #define EQUAL(cp,cs) (((cp)==(cs))||(ISSET(PARAM_I)&&((cp)==toupper(cs)))) while(j>0&&!EQUAL(P[j],S[i])) j=L[j-1]; if(EQUAL(P[j],S[i])) j++; if(!P[j]){ M=&S[l=((i-j)+1)]; if(!ISSET(PARAM_N)){ for(k=0,N=M;!(N<S);N--) if((*N)&0x80) k++; if(!(k&0x01)) continue; } if(!p&&!(p=localtime(×tamp))) continue; count++; fprintf(out,"%6d %-20.20s %4d %4s %04d%02d%02d%02d%02d%02d %-17.17s %6d %-13.13s %s\n", n,b->filename,current,mode,(p->tm_year+1900),(p->tm_mon+1),(p->tm_mday), (p->tm_hour),(p->tm_min),(p->tm_sec),f->filename,l,f->owner,f->title); if(ISSET(PARAM_S)) break; j=L[j-1]; } #undef EQUAL } munmap(vp,st.st_size); number++; } while(0); return 0; } static inline int process_board(const struct boardheader *b,int n,void *v){ static char name[BOUND]; do{ if(ISSET(PARAM_A)) break; if(ISSET(PARAM_U)){ if(!check_read_perm(user,b)) return -1; break; } if(ISSET(PARAM_B)) break; if(!public_board(b)) return -2; } while(0); current=n; if(!ISSET(PARAM_Q)) fprintf(stdout,"正在处理版面 %-29.29s ... ",b->filename); if(!ISSET(PARAM_E)){ mode="版面"; setbdir(DIR_MODE_NORMAL,name,b->filename); APPLY_RECORD(name,process_article,sizeof(struct fileheader),b,0,true); } if(ISSET(PARAM_D)){ mode="回收"; setbdir(DIR_MODE_DELETED,name,b->filename); APPLY_RECORD(name,process_article,sizeof(struct fileheader),b,0,true); } if(ISSET(PARAM_J)){ mode="自删"; setbdir(DIR_MODE_JUNK,name,b->filename); APPLY_RECORD(name,process_article,sizeof(struct fileheader),b,0,true); } if(!ISSET(PARAM_Q)) fprintf(stdout,"%s\n","处理完成!"); return 0; } int main(int argc,char **argv){ #define EXIT(msg) do{fprintf(stderr,"%s\n",(msg));if(out)fclose(out);exit(__LINE__);}while(0) const struct boardheader *board; char name[BOUND],path[BOUND]; const char *desc; int ret; double cost; if(!getcwd(path,BOUND)) EXIT("获取当前工作目录时发生错误"); if(chdir(BBSHOME)==-1) EXIT("切换工作目录时发生错误..."); if((mark=time(NULL))==(time_t)(-1)) EXIT("获取时间时发生错误..."); resolve_ucache(); resolve_boards(); to=mark; opterr=0; while((ret=getopt(argc,argv,"r:f:t:ab:u:p:djesnio:qh"))!=-1){ switch(ret){ #define CHECK_CONFLICT(param) do{if(ISSET(param))EXIT("给定的选项间存在冲突...");}while(0) #define CHECK_DEPENDENCE(param) do{if(!ISSET(param))EXIT("给定的选项间缺少依赖...");}while(0) #define CHECK_DUP(param) do{if(ISSET(param))EXIT("给定的选项中存在重复...");}while(0) #define SET(param) do{CHECK_DUP(param);flag|=(param);}while(0) case 'r': CHECK_CONFLICT(PARAM_F|PARAM_T); SET(PARAM_R); do{ struct tm t,*p; int n; if(!isdigit(optarg[0])) EXIT("选项 -r 的参数无法解析..."); n=atoi(optarg); if(!(p=localtime(&mark))) EXIT("解析时间时发生错误..."); memcpy(&t,p,sizeof(struct tm)); t.tm_hour=0; t.tm_min=0; t.tm_sec=0; if((from=mktime(&t))==(time_t)(-1)) EXIT("设定时间时发生错误..."); } while(0); break; #define PARSE2(p) ((((p)[0]*10)+((p)[1]*1))-('0'*11)) #define PARSE4(p) ((PARSE2(p)*100)+(PARSE2(&(p)[2])*1)) case 'f': CHECK_CONFLICT(PARAM_R); SET(PARAM_F); do{ struct tm t; int i; for(i=0;optarg[i];i++) if(!isdigit(optarg[i])) break; if(i!=14) EXIT("选项 -f 的参数无法解析..."); memset(&t,0,sizeof(struct tm)); t.tm_year=(PARSE4(optarg)-1900); t.tm_mon=(PARSE2(&optarg[4])-1); t.tm_mday=PARSE2(&optarg[6]); t.tm_hour=PARSE2(&optarg[8]); t.tm_min=PARSE2(&optarg[10]); t.tm_sec=PARSE2(&optarg[12]); if((from=mktime(&t))==(time_t)(-1)) EXIT("设定时间时发生错误..."); } while(0); break; case 't': CHECK_CONFLICT(PARAM_R); SET(PARAM_T); do{ struct tm t; int i; for(i=0;optarg[i];i++) if(!isdigit(optarg[i])) break; if(i!=14) EXIT("选项 -t 的参数无法解析..."); memset(&t,0,sizeof(struct tm)); t.tm_year=(PARSE4(optarg)-1900); t.tm_mon=(PARSE2(&optarg[4])-1); t.tm_mday=PARSE2(&optarg[6]); t.tm_hour=PARSE2(&optarg[8]); t.tm_min=PARSE2(&optarg[10]); t.tm_sec=PARSE2(&optarg[12]); if((from=mktime(&t))==(time_t)(-1)) EXIT("设定时间时发生错误..."); } while(0); break; #undef PARSE2 #undef PARSE4 case 'a': CHECK_CONFLICT(PARAM_B|PARAM_U); SET(PARAM_A); break; case 'b': CHECK_CONFLICT(PARAM_A|PARAM_U); SET(PARAM_B); if(!(current=getbid(optarg,&board))) EXIT("选项 -b 所指定的版面无法获取..."); break; case 'u': CHECK_CONFLICT(PARAM_A|PARAM_B); SET(PARAM_U); do{ struct userec *u; if(!getuser(optarg,&u)) EXIT("选项 -u 所指定的用户无法获取..."); user=u; } while(0); break; case 'p': SET(PARAM_P); snprintf(post,OWNER_LEN,"%s",optarg); break; case 'd': SET(PARAM_D); break; case 'j': SET(PARAM_J); break; case 'e': CHECK_DEPENDENCE(PARAM_D|PARAM_J); SET(PARAM_E); break; case 's': SET(PARAM_S); break; case 'n': SET(PARAM_N); break; case 'i': SET(PARAM_I); break; case 'o': SET(PARAM_O); if(optarg[0]!='/') snprintf(name,BOUND,"%s/%s",path,optarg); else snprintf(name,BOUND,"%s",optarg); break; case 'q': SET(PARAM_Q); break; case 'h': usage(); return 0; default: usage(); EXIT("不可识别的选项..."); break; #undef CHECK_CONFLICT #undef CHECK_DEPENDENCE #undef CHECK_DUP #undef SET } } if(from>to){ usage(); EXIT("当前时间设定不合法..."); } if(!ISSET(PARAM_Q)&&setvbuf(stdout,NULL,_IONBF,BUFSIZ)) EXIT("调整文件缓冲时发生错误..."); if((argc-optind)!=1){ usage(); EXIT("不可识别的参数..."); } set_pattern(argv[optind]); set_link(argv[optind]); if(!size) EXIT("模式串不能为空串..."); if(!ISSET(PARAM_O)) snprintf(name,BOUND,"%s/res_%lu.us",path,mark); if(!(out=fopen(name,"w"))) EXIT("打开文件时发生错误..."); fprintf(out,"%6s %-20.20s %4s %4s %-14.14s %-17.17s %6s %-13.13s %s\n", "文章号","版面名称"," BID","位置","发表时间","文件名","偏移量","作者","标题"); if(!(P[0]&0x80)) flag|=PARAM_N; if(ISSET(PARAM_B)) process_board(board,current,NULL); else APPLY_BIDS(process_board,NULL); fclose(out); cost=difftime(time(NULL),mark); if(cost>86400){ cost/=86400; desc="天"; } else if(cost>3600){ cost/=3600; desc="小时"; } else if(cost>60){ cost/=60; desc="分钟"; } else desc="秒"; fprintf(stdout,"\n操作已完成! 共处理 %d 篇文章, 获得 %d 处匹配, 耗时 %.2lf %s!\n", number,count,cost,desc); return 0; #undef EXIT }
char * ann_numtopath(char *path, char *numpath, struct userec *user) { int bid=0; char *c; char *ptr = NULL; const struct boardheader *bh = NULL; char filename[256]; FILE *fp; char buf[256]; int endfile=0; char currpath[256]; char title[STRLEN]; int ok; path[0]='\0'; title[0]='\0'; currpath[0]='\0'; while(1){ if(path[0]=='\0'){ c=strchr(numpath, '-'); if(c!=NULL) *c='\0'; bid = atoi(numpath); if((bh=getboard(bid))==NULL) return NULL; if (check_read_perm(user, bh) == 0) return NULL; snprintf(path,255,"0Announce/groups/%s",bh->ann_path); if(c==NULL) break; ptr = c + 1; continue; }else{ if(ptr[0]=='\0') break; c = strchr(ptr, '-'); if(c==NULL) endfile=1; else{ *c='\0'; } bid = atoi(ptr); if(c!=NULL) ptr = c+1; if(bid <=0) return NULL; } snprintf(filename, sizeof(filename), "%s/.Names", path); ok = 0; if ((fp = fopen(filename, "r")) == NULL) return NULL; while (fgets(buf, sizeof(buf), fp) != NULL) { if ((c = strrchr(buf, '\n')) != NULL) *c = '\0'; if (strncmp(buf, "Name=", 5) == 0) { strncpy(title, buf + 5, sizeof(title) - 1); title[sizeof(title) - 1] = '\0'; continue; }else if (strncmp(buf, "Path=~/", 7) == 0){ snprintf(currpath, sizeof(currpath), "%s/%s", path, buf + 7); continue; }else if (strncmp(buf, "Path=", 5) == 0){ snprintf(currpath, sizeof(currpath), "%s/%s", path, buf + 5); continue; }else if(strncmp(buf, "Numb=", 5) == 0){ if(bid != atoi(buf+5)){ title[0]='\0'; currpath[0]='\0'; continue; } if (ann_can_access(title, bh->filename, user) == 0) { break; }else{ ok = 1; strcpy(path, currpath); break; } }else continue; } fclose(fp); if(!ok) return NULL; if(endfile) break; } if(path[0]=='/' || strncmp(path, "0Announce/groups/", 17) || strstr(path, "..") ) return NULL; return path; }
/* 返回值意义: -1 没有权限 0 有看的权限 1 有管理的权限 */ int ann_traverse_check(char *path, struct userec *user) { char *ptr; char *ptr2; size_t i = 0; char filename[256]; char buf[256], *fnameptr; char pathbuf[256]; char currpath[256]; char title[STRLEN]; FILE *fp; char board[STRLEN]; bool has_perm_boards = false, sysop_only = false; char *bmstr; int bms_level = 0; /* path parameter can not have leading '/' character */ if (path[0] == '/') return -1; board[0] = '\0'; if ((ptr = strstr(path, "groups/")) != NULL) ann_get_board(ptr, board, sizeof(board)); bzero(pathbuf, sizeof(pathbuf)); if (board[0] == '\0') { ptr = path; } else { const struct boardheader *bh; bh = getbcache(board); if (check_read_perm(user, bh) == 0) return -1; ann_get_path(board, filename, sizeof(filename)); snprintf(pathbuf, sizeof(pathbuf), "0Announce%s", filename); ptr = path + strlen(pathbuf); i = strlen(pathbuf); /* 如果是本版版主 则获得版主权限 TODO */ if (chk_currBM(bh->BM, user)) has_perm_boards = true; } /* 如果是站务 则获得版主权限 */ if (HAS_PERM(user, PERM_OBOARDS) || HAS_PERM(user, PERM_ANNOUNCE) || HAS_PERM(user, PERM_SYSOP)) has_perm_boards = true; /* 开始逐级判断权限 */ while (*ptr != '\0') { if (*ptr == '/') { snprintf(filename, sizeof(filename), "%s/.Names", pathbuf); } else { if (i < sizeof(pathbuf)) pathbuf[i] = *ptr; ptr++; i++; continue; } if ((fp = fopen(filename, "r")) == NULL) return -1; while (fgets(buf, sizeof(buf), fp) != NULL) { if ((ptr2 = strrchr(buf, '\n')) != NULL) *ptr2 = '\0'; if (strncmp(buf, "Name=", 5) == 0) { strncpy(title, buf + 5, sizeof(title) - 1); title[sizeof(title) - 1] = '\0'; continue; } if (strncmp(buf, "Path=~/", 7) == 0) fnameptr = buf + 7; else if (strncmp(buf, "Path=", 5) == 0) fnameptr = buf + 5; else continue; snprintf(currpath, sizeof(currpath), "%s/%s", pathbuf, fnameptr); if (strncmp(currpath, path, strlen(currpath)) != 0) continue; if (path[strlen(currpath)] != '/' && path[strlen(currpath)]!='\0' ) continue; /* 如果有指定BM 则按BM名单获得版主权限 */ bmstr = strstr(title, "(BM:"); if (bmstr != NULL) if (chk_currBM(bmstr + 4, user)) has_perm_boards = true; /* 如果指定BMS 则目录的版主权限级别升高 */ if (strstr(title, "(BM: BMS)")) bms_level++; /* 如果指定SYSOPS 则目录为仅站务可见 */ if (strstr(title, "(BM: SYSOPS)")) sysop_only = true; #ifdef ANN_CTRLK /* 如果Ctrl+K权限验证不通过 则禁止 */ if(!canread(has_perm_boards ? PERM_BOARDS : 0, pathbuf, fnameptr, title)) { fclose(fp); return -1; } #endif /* 如果在一级BMS目录下且用户不具备版主权限 则禁止 */ if ((bms_level >=1) && !HAS_PERM(user, PERM_BOARDS)) { fclose(fp); return -1; } /* 如果在二级BMS目录下且用户不具备本版版主权限 则禁止 */ if ((bms_level >=2) && !has_perm_boards) { fclose(fp); return -1; } /* 如果在SYSOPS目录下且用户不是站务 则禁止 */ if (sysop_only && !HAS_PERM(user, PERM_SYSOP)) { fclose(fp); return -1; } break; } if (feof(fp)) { fclose(fp); return -1; } fclose(fp); if (i < sizeof(pathbuf)) pathbuf[i] = *ptr; ptr++; i++; } return has_perm_boards ? 1 : 0; }