/* $Id$ */ #include "bbs.h" #ifndef NEW_AIDS #error "Not complete yet" #endif aidu_t fn2aidu(const char *fn) { aidu_t aidu = 0; aidu_t type = 0; aidu_t v1 = 0; aidu_t v2 = 0; char fnbuf[FNLEN + 1]; char *sp = NULL; if(fn == NULL) return 0; strncpy(fnbuf, fn, FNLEN); fnbuf[FNLEN] = '\0'; sp = fnbuf; switch(*(sp ++)) { case 'M': type = 0; break; case 'G': type = 1; break; default: return 0; break; } if(*(sp ++) != '.') return 0; v1 = strtoul(sp, &sp, 10); if(sp == NULL) return 0; if(*sp != '.' || *(sp + 1) != 'A') return 0; sp += 2; if(*(sp ++) == '.') { v2 = strtoul(sp, &sp, 16); if(sp == NULL) return 0; } aidu = ((type & 0xf) << 44) | ((v1 & 0xffffffff) << 12) | (v2 & 0xfff); return aidu; } /* IMPORTANT: * size of buf must be at least 8+1 bytes */ char *aidu2aidc(char *buf, const aidu_t orig_aidu) { const char aidu2aidc_table[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_"; const int aidu2aidc_tablesize = sizeof(aidu2aidc_table) - 1; char *sp = buf + 8; aidu_t aidu = orig_aidu; aidu_t v; *(sp --) = '\0'; while(sp >= buf) { /* FIXME: 能保證 aidu2aidc_tablesize 是 2 的冪次的話, 這裡可以改用 bitwise operation 做 */ v = aidu % aidu2aidc_tablesize; aidu = aidu / aidu2aidc_tablesize; *(sp --) = aidu2aidc_table[v]; } return buf; } /* IMPORTANT: * size of fn must be at least FNLEN bytes */ char *aidu2fn(char *fn, const aidu_t aidu) { aidu_t type = ((aidu >> 44) & 0xf); aidu_t v1 = ((aidu >> 12) & 0xffffffff); aidu_t v2 = (aidu & 0xfff); if(fn == NULL) return NULL; snprintf(fn, FNLEN, "%c.%d.A.%03X", ((type == 0) ? 'M' : 'G'), (unsigned int)v1, (unsigned int)v2); return fn; } aidu_t aidc2aidu(const char *aidc) { const char *sp = aidc; aidu_t aidu = 0; if(aidc == NULL) return 0; while(*sp != '\0' && /* ignore trailing spaces */ *sp != ' ') { aidu_t v = 0; /* FIXME: 查表法會不會比較快? */ if(*sp >= '0' && *sp <= '9') v = *sp - '0'; else if(*sp >= 'A' && *sp <= 'Z') v = *sp - 'A' + 10; else if(*sp >= 'a' && *sp <= 'z') v = *sp - 'a' + 36; else if(*sp == '-') v = 62; else if(*sp == '_') v = 63; else if(*sp == '@') break; else return 0; aidu <<= 6; aidu |= (v & 0x3f); sp ++; } return aidu; } int search_aidu_in_bfile(const char *bfile, const aidu_t aidu) { char fn[FNLEN]; int fd; fileheader_t fhs[64]; int len, i; int pos = 0; int found = 0; int lastpos = 0; if(aidu2fn(fn, aidu) == NULL) return -1; if((fd = open(bfile, O_RDONLY, 0)) < 0) return -1; while(!found && (len = read(fd, fhs, sizeof(fhs))) > 0) { len /= sizeof(fileheader_t); for(i = 0; i < len; i ++) { int l; if(strcmp(fhs[i].filename, fn) == 0 || ((aidu & 0xfff) == 0 && (l = strlen(fhs[i].filename)) > 6 && strncmp(fhs[i].filename, fn, l) == 0)) { if(fhs[i].filemode & FILE_BOTTOM) { lastpos = pos; } else { found = 1; break; } } pos ++; } } close(fd); return (found ? pos : (lastpos ? lastpos : -1)); } int search_aidu_in_board(SearchAIDResult_t *r, const char *bname, const aidu_t aidu) { int n = -1; char dirfile[PATHLEN]; if(r == NULL) return -1; r->n = -1; /* search bottom */ { char bf[FNLEN]; snprintf(bf, FNLEN, "%s.bottom", FN_DIR); setbfile(dirfile, bname, bf); if((n = search_aidu_in_bfile(dirfile, aidu)) >= 0) { r->where = AIDR_BOTTOM; r->n = n; } } /* else search board */ if(r->n < 0) { setbfile(dirfile, bname, FN_DIR); if((n = search_aidu_in_bfile(dirfile, aidu)) >= 0) { r->where = AIDR_BOARD; r->n = n; } } /* else search digest */ if(r->n < 0) { setbfile(dirfile, bname, fn_mandex); if((n = search_aidu_in_bfile(dirfile, aidu)) >= 0) { r->where = AIDR_DIGEST; r->n = n; } } return r->n; } int do_search_aid(SearchAIDResult_t *r) { char aidc[100]; char bname[IDLEN + 1] = ""; aidu_t aidu = 0; char *sp; char *sp2; char *emsg = NULL; if(r == NULL) return -1; r->n = -1; if(!getdata(b_lines, 0, "搜尋" AID_DISPLAYNAME ": #", aidc, 15 + IDLEN, LCECHO)) { move(b_lines, 0); clrtoeol(); return -1; } if(currstat == RMAIL) { move(21, 0); clrtobot(); move(22, 0); prints("此狀態下無法搜尋" AID_DISPLAYNAME); pressanykey(); return -1; } sp = aidc; while(*sp == ' ') sp ++; while(*sp == '#') sp ++; aidu = aidc2aidu(sp); if((sp2 = strchr(sp, '@')) != NULL) { // assert(sizeof(bname) > IDLEN); strlcpy(bname, sp2 + 1, IDLEN+1); *sp2 = '\0'; } else bname[0] = '\0'; if(aidu > 0) { if(bname[0] != '\0') { if(!HasBoardPerm_bn(bname)) return -1; search_aidu_in_board(r, bname, aidu); if(r->n >= 0) { if(enter_board(bname) < 0) { r->n = -1; emsg = "錯誤:無法進入指定的看板 %s"; } } } else { search_aidu_in_board(r, currboard, aidu); } } if(r->n < 0) { if(aidu == 0) emsg = "不合法的" AID_DISPLAYNAME ",請確定輸入是正確的"; else if(emsg == NULL) { if(bname[0] != '\0') emsg = "看板 %s 內找不到這個" AID_DISPLAYNAME ",可能是文章已經消失,或是找錯看板了"; else emsg = "找不到這個" AID_DISPLAYNAME ",可能是文章已經消失,或是找錯看板了"; } move(21, 0); clrtoeol(); move(22, 0); prints(emsg, bname); pressanykey(); r->n = -1; return r->n; } else { return r->n; } }