/* $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;
}
}