Example #1
0
static int get_only_postno(const char *dotdir, int fd, FILEHEADER *fhr)
{
	char finfo[PATHLEN];
	INFOHEADER info;

	if (get_last_info(dotdir, fd, &info, FALSE) == -1) {
		bbslog("ERROR", "Getting INFO_REC.");
		fprintf(stderr, "ERROR: Getting INFO_REC.");
		return -1;
	}

	if (++info.last_postno > BRC_REALMAXNUM)
		info.last_postno = 1;	/* reset the postno. */

	fhr->postno = info.last_postno;
	info.last_mtime  = fhr->mtime;
	strcpy(info.last_filename, fhr->filename);

	setdotfile(finfo, dotdir, INFO_REC);
	if (substitute_record(finfo, &info, IH_SIZE, 1) == -1) {
		bbslog("ERROR", "Updating INFO_REC. (%s)", finfo);
		fprintf(stderr, "ERROR: Updating INFO_REC. (%s)", finfo);
		return -1;
	}

	return 0;
}
Example #2
0
/*
 * immediately remove article which were mark deleted
 */
int pack_article(const char *direct)
{
	int fdr, fdw;
	FILEHEADER fhr;
	FILE *fhw;
	char fn_dirty[PATHLEN];
	int result = 0;

	if ((fdr = open(direct, O_RDWR)) < 0)
		return -1;
	if (myflock(fdr, LOCK_EX)) {
		close(fdr);
		return -1;
	}
	fhw = tmpfile();
	fdw = fileno(fhw);
	while (myread(fdr, &fhr, FH_SIZE) == FH_SIZE)
	{
		if ((fhr.accessed & FILE_DELE))
		{
			setdotfile(fn_dirty, direct, fhr.filename);
			unlink(fn_dirty);
			++result;
		}
		else
		{
			if (mywrite(fdw, &fhr, FH_SIZE) != FH_SIZE)
			{
				result = -1;
				break;
			}
		}
	}
	if (result > 0)
		result = myfdcp(fdw, fdr);
	fclose(fhw);
	flock(fdr, LOCK_UN);
	close(fdr);
	return result;
}
Example #3
0
/*
 * Delete records pointed to missing article file
 */
int clean_dirent(const char *direct)
{
	int fdr, fdw, fdt;
	FILEHEADER fhr;
	FILE *fhw;
	char fn_dirty[PATHLEN];
	int result = 0;

	if ((fdr = open(direct, O_RDWR)) < 0)
		return -1;
	if (myflock(fdr, LOCK_EX)) {
		close(fdr);
		return -1;
	}
	fhw = tmpfile();
	fdw = fileno(fhw);
	while (myread(fdr, &fhr, FH_SIZE) == FH_SIZE)
	{
		if (fhr.filename[0]) {
			fhr.filename[sizeof(fhr.filename)-1] = '\0';
			setdotfile(fn_dirty, direct, fhr.filename);
			if ((fdt = open(fn_dirty, O_RDONLY)) > 0) {
				close(fdt);
				if (mywrite(fdw, &fhr, FH_SIZE) != FH_SIZE) {
					result = -1;
					break;
				}
				++result;
			}
		}
	}
	if (result > 0)
		result = myfdcp(fdw, fdr);
	close(fdw);
	flock(fdr, LOCK_UN);
	close(fdr);
	return result;
}
Example #4
0
File: bbsweb.c Project: wtj/formosa
/*******************************************************************
 *	根據 URLParaType 執行 POST 的要求
 *
 *	return HttpRespondType
 *******************************************************************/
int 
DoPostRequest(REQUEST_REC * r, BOARDHEADER * board, POST_FILE * pf)
{
	int result, URLParaType;
	char *form_data, *boardname;

	result = WEB_ERROR;
	URLParaType = r->URLParaType;
	boardname = board->filename;

	/* 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

	if (PSCorrect == nLogin && URLParaType == PostSend)
	{
		/* PostSend allow username&password in form body without login */
		char pass[PASSLEN * 3];

		GetPara2(username, "Name", form_data, IDLEN, "");	/* get userdata from form */
		GetPara2(pass, "Password", form_data, PASSLEN * 3, "");
		Convert(pass, 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 == AccessListModify
		)
	{
		int perm;
		/* boardname should set in advance, now in ParseURI() */
		if (get_board(board, boardname) <= 0 || board->filename[0] == '\0')
			return WEB_BOARD_NOT_FOUND;
		if ((perm = CheckBoardPerm(board, &curuser)) != WEB_OK)
			return perm;
	}

	if (PSCorrect == Correct
	    || (PSCorrect == gLogin && (URLParaType == PostSend || URLParaType == TreaSend))
	    || URLParaType == UserNew)
	{
		int start, end;
		char path[PATHLEN];

		switch (URLParaType)
		{
			case PostSend:
			case TreaSend:
				if ((result = PostArticle(form_data, board, pf)))
				{
#if 1
					if (URLParaType == TreaSend)
					{
						if (strlen(pf->POST_NAME))
							sprintf(skin_file->filename, "/%streasure/%s/%s/$",
								BBS_SUBDIR, boardname, pf->POST_NAME);
						else
							sprintf(skin_file->filename, "/%streasure/%s/$",
								BBS_SUBDIR, boardname);
					}
					else
					{
						sprintf(skin_file->filename, "/%sboards/%s/",
						     BBS_SUBDIR, boardname);
					}
#endif

					if (PSCorrect == Correct)
						UpdateUserRec(URLParaType, &curuser, board);
				}
				break;

			case MailSend:
				if ((result = PostArticle(form_data, board, pf)))
				{
					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)))
				{
					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:
				if ((result = DeleteArticle(form_data, board, pf)))
				{
					if (URLParaType == PostDelete)
					{
						find_list_range(&start, &end, pf->num, DEFAULT_PAGE_SIZE, pf->total_rec);
						sprintf(skin_file->filename, "/%sboards/%s/%d-%d",
							BBS_SUBDIR, boardname, start, end);
					}
					else if (URLParaType == TreaDelete)
					{
						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)))
					sprintf(skin_file->filename, "%s%s%s",
						HTML_PATH, BBS_SUBDIR, HTML_UserNewOK);
				break;

			case UserIdent:
				if ((result = DoUserIdent(form_data, &curuser)))
					sprintf(skin_file->filename, "%s%s%s",
						HTML_PATH, BBS_SUBDIR, HTML_UserIdentOK);
				break;

			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.17.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, boardname, 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)))
Example #5
0
/*******************************************************************
 *	從 .DIR 中讀取 POST 相關資訊
 *
 *	佈告區 & 精華區 & 信件 通用
 *******************************************************************/
int GetPostInfo(BOARDHEADER *board, POST_FILE *pf)
{
	int fd;
	time_t date;
#ifdef USE_MMAP
	FILEHEADER *fileinfo;
	int i;
#else
	FILEHEADER fileinfo;
#endif
	char *p, board_dir[PATHLEN];

	/* ====== get post info from DIR_REC ====== */

	setdotfile(board_dir, pf->POST_NAME, DIR_REC);
	pf->total_rec = get_num_records(board_dir, FH_SIZE);

	if((pf->total_rec == 0)
	|| (p = strrchr(pf->POST_NAME, '/')) == NULL)
		return WEB_FILE_NOT_FOUND;
	xstrncpy(pf->fh.filename, p+1, STRLEN-8-12-4-4);

#if 0
	fprintf(fp_out, "[board_dir=%s, total_post=%d, pf->POST_NAME=%s, pf->fh.filename=%s]\n", board_dir, pf->total_rec, pf->POST_NAME, pf->fh.filename);
	fflush(fp_out);
#endif

	if ((fd = open(board_dir, O_RDWR)) < 0)
		return WEB_FILE_NOT_FOUND;

	/* seek from .DIR back is better */
	pf->num = pf->total_rec;

#ifdef USE_MMAP
	fileinfo = (FILEHEADER *) mmap((caddr_t) 0,
		(size_t)(pf->total_rec*FH_SIZE),
		(PROT_READ | PROT_WRITE),
		MAP_SHARED, fd, (off_t) 0);

	if(fileinfo == MAP_FAILED)
	{
		sprintf(WEBBBS_ERROR_MESSAGE, "mmap failed: %s %d",
			strerror(errno), (int)(pf->total_rec*FH_SIZE));
		close(fd);
		return WEB_ERROR;
	}
	close(fd);

	while(pf->num > 0)
	{
		if(!strcmp((fileinfo+pf->num-1)->filename, pf->fh.filename))
		{
			if((fileinfo+pf->num-1)->accessed & FILE_DELE)
			{
				munmap((void *)fileinfo, pf->total_rec*FH_SIZE);
				return WEB_FILE_NOT_FOUND;
			}
			break;
		}
		pf->num--;
	}

	if(pf->num < 1)
	{
		munmap((void *)fileinfo, pf->total_rec*FH_SIZE);
		return WEB_FILE_NOT_FOUND;
	}
	memcpy(&(pf->fh), fileinfo+pf->num-1, FH_SIZE);

#else

	if(lseek(fd, (FH_SIZE*(pf->total_rec-1)), SEEK_SET) == -1)
		return WEB_FILE_NOT_FOUND;

	while(pf->num >= 0)
	{
		if(read(fd, &fileinfo, FH_SIZE)==FH_SIZE)
		{
			if(!strcmp(fileinfo.filename, pf->fh.filename))
			{
				if(fileinfo.accessed & FILE_DELE)
				{
					close(fd);
					return WEB_FILE_NOT_FOUND;
				}
				break;
			}

			pf->num--;
			lseek(fd, -(FH_SIZE*2), SEEK_CUR);
		}
		else
		{
			close(fd);
			return WEB_FILE_NOT_FOUND;
		}
	}

#if 0
	/* search from head */
	pf->num = 0;
	while (read(fd, &fileinfo, FH_SIZE) == FH_SIZE)
	{
		pf->num++;
		if (!strcmp(fileinfo.filename, pf->fh.filename))
		{
			if(fileinfo.accessed & FILE_DELE)
			{
				close(fd);
				return WEB_FILE_NOT_FOUND;
			}
			break;
		}
	}
#endif

	memcpy(&(pf->fh), &(fileinfo), FH_SIZE);

#endif	/* USE_MMAP */

	date = atol((pf->fh.filename) + 2);	/* get date from filename */
	xstrncpy(pf->date, ctime(&date), STRLEN);

	if(request_rec->HttpRequestType != GET)
	{
		/* skip find last & next post info if not HTTP_GET */
#ifdef USE_MMAP
		munmap((void *)fileinfo, pf->total_rec*FH_SIZE);
#else
		close(fd);
#endif
		return WEB_OK;
	}

	if(request_rec->URLParaType == MailRead
	&& (pf->fh.accessed & FILE_READ) == FALSE)
	{
		int maxkeepmail;

		if (curuser.userlevel == PERM_BM)
			maxkeepmail = SPEC_MAX_KEEP_MAIL;
		else
			maxkeepmail = MAX_KEEP_MAIL;

		if(curuser.userlevel != PERM_SYSOP
		&& pf->num > maxkeepmail )	/* lthuang */
		{
#ifdef USE_MMAP
			munmap((void *)fileinfo, pf->total_rec*FH_SIZE);
#else
			close(fd);
#endif
			sprintf(WEBBBS_ERROR_MESSAGE, "%s 信箱已滿 ( %d 封), 請刪除舊信後再看新信...",
				curuser.userid, pf->total_rec);
			return WEB_ERROR;
		}

		/* set fileinfo as readed */
#ifdef USE_MMAP
		(fileinfo+pf->num-1)->accessed |= FILE_READ;

#else
		if (lseek(fd, -FH_SIZE, SEEK_CUR) == -1)
		{
			close(fd);
			return WEB_FILE_NOT_FOUND;
		}

		fileinfo.accessed |= FILE_READ;
		write(fd, &fileinfo, FH_SIZE);
#endif

	}

#ifdef TORNADO_OPTIMIZE
#if defined(NSYSUBBS1) || defined(NSYSUBBS3)
	if(isTORNADO && request_rec->URLParaType == PostRead)
	{
		if(pf->total_rec - pf->num > TORNADO_GET_MAXPOST)
		{
			strcpy(pf->lfname, "-1");
			strcpy(pf->nfname, "-1");
#ifdef USE_MMAP
			munmap((void *)fileinfo, pf->total_rec*FH_SIZE);
#else
			close(fd);
#endif
			return WEB_OK;
		}
	}
#endif
#endif

	/* get previous post filename */
#ifdef USE_MMAP
	for(i=pf->num-1; i>0; i--)
	{
		if(*((fileinfo+i-1)->filename) != 0x00
		&& !((fileinfo+i-1)->accessed & FILE_DELE)
		&& !((fileinfo+i-1)->accessed & FILE_TREA))
		{
			xstrncpy(pf->lfname, (fileinfo+i-1)->filename, STRLEN-8);
			break;
		}
	}
	if(i <= 0)
		strcpy(pf->lfname, "-1");

#else
	while(1)
	{
		if(lseek(fd, -(FH_SIZE*2), SEEK_CUR) == -1)
		{
			strcpy(pf->lfname, "-1");
			break;
		}
		if(read(fd, &fileinfo, FH_SIZE)==FH_SIZE)
		{
			if( *fileinfo.filename != 0x00
			&& !(fileinfo.accessed & FILE_DELE)
			&& !(fileinfo.accessed & FILE_TREA))
			{
            	xstrncpy(pf->lfname, fileinfo.filename, STRLEN-8);
				break;
			}
		}
	}
#endif	/* USE_MMAP */


	if(strcmp(pf->lfname, "-1"))
#ifdef USE_MMAP
		if((fileinfo+i-1)->accessed & FILE_HTML)
#else
		if(fileinfo.accessed & FILE_HTML)
#endif
			pf->type |= LAST_POST_IS_HTML;

#if 0
	fprintf(fp_out, "[file_num=%d, last_filename=%s]", pf->num, pf->lfname);
	fflush(fp_out);
#endif

	/* get next post filename */
#ifdef USE_MMAP
	for(i=pf->num+1; i<=pf->total_rec; i++)
	{
		if(*((fileinfo+i-1)->filename) != 0x00
		&& !((fileinfo+i-1)->accessed & FILE_DELE)
		&& !((fileinfo+i-1)->accessed & FILE_TREA))
		{
			xstrncpy(pf->nfname, (fileinfo+i-1)->filename, STRLEN-8);
			break;
		}
	}

	if(i >= pf->total_rec+1)
		strcpy(pf->nfname, "-1");

#else

	if (lseek(fd, (long) (FH_SIZE * (pf->num)), SEEK_SET) == -1)
    {
		close(fd);
		return WEB_FILE_NOT_FOUND;
	}

	while(1)
    {
		if(read(fd, &fileinfo, FH_SIZE)==FH_SIZE)
       	{
			if( *fileinfo.filename != 0x00
			&& !(fileinfo.accessed & FILE_DELE)
			&& !(fileinfo.accessed & FILE_TREA))
			{
				xstrncpy(pf->nfname, fileinfo.filename, STRLEN-8);
				break;
			}
		}
       	else
       	{
       		strcpy(pf->nfname, "-1");
       		break;
       	}
	}
#endif	/* USE_MMAP */


	if(strcmp(pf->nfname, "-1"))
#ifdef USE_MMAP
		if((fileinfo+i-1)->accessed & FILE_HTML)
#else
		if(fileinfo.accessed & FILE_HTML)
#endif
			pf->type |= NEXT_POST_IS_HTML;

#if 0
	fprintf(fp_out, "[next_filename=%s]", pf->nfname);
	fflush(fp_out);
#endif

#ifdef USE_MMAP
	munmap((void *)fileinfo, pf->total_rec*FH_SIZE);
#else
	close(fd);
#endif
	return WEB_OK;
}
Example #6
0
/*
 * postno is for readrc mechanism
 * It reads the last postno information from INFO_REC
 * If failed, scan all .DIR file to find the last postno.
 * and write it back to INFO_REC.
 */
int get_last_info(const char *dotdir, int fd, INFOHEADER *info, int force)
{
	char finfo[PATHLEN];

	setdotfile(finfo, dotdir, INFO_REC);
	if (force || (get_record(finfo, info, IH_SIZE, 1) != 0)) {
		int i, nr, myfd;
		FILEHEADER lastf, fhtmp;
		time_t lastmtime = 0, mtime;

		if (!dotdir && !fd)
			return -1;

		if (!fd) {
			myfd = open(dotdir, O_RDWR | O_CREAT, 0644);
			if (myfd == -1)
				return -1;
			if (myflock(myfd, LOCK_EX)) {
				close(myfd);
				return -1;
			}
		} else {
			myfd = fd;
		}

		nr = get_num_records_byfd(myfd, FH_SIZE);
		for (i = 1; i <= nr; ++i) {
			if (get_record_byfd(myfd, &fhtmp, FH_SIZE, i) == 0) {
				if (fhtmp.accessed & FILE_DELE)
					continue;

				if (fhtmp.mtime)
					mtime = fhtmp.mtime;
				else if (fhtmp.filename[0] == 'M')
					mtime = strtol(fhtmp.filename + 2, NULL, 10);
				else
					mtime = 0;

				if (mtime > lastmtime) {
					memcpy(&lastf, &fhtmp, FH_SIZE);
					lastmtime = mtime;
				}
			} else {
				break;
			}
		}

		if (!fd) {
			flock(myfd, LOCK_UN);
			close(myfd);
		}

		if (i <= nr)
			return -1;

		memset(info, 0, IH_SIZE);
		if (lastmtime) {
			info->last_postno = lastf.postno;
			info->last_mtime  = lastf.mtime;
			strcpy(info->last_filename, lastf.filename);
		} else {
			/* There is no article yet. */
			info->last_postno = 0;
			info->last_mtime = 0;
			strcpy(info->last_filename, "M.000000000.A");
		}
		if (substitute_record(finfo, info, IH_SIZE, 1) == -1)
			return -1;
	}

	return 0;
}
Example #7
0
int recover_dirent(const char *direct)
{
	struct file_list *dl;
	size_t dl_size;
	int i = 0, cmp, fdr, fdw;
	char dirpath[PATHLEN];
	FILEHEADER fhr, nfhr;
	FILE *fhw;
	int result = 0;

	setdotfile(dirpath, direct, NULL);
	dl = get_file_list(dirpath, &dl_size, "M.");
	if (!dl)
		return -1;

	qsort(dl, dl_size, sizeof(struct file_list), cmpfun);

	if ((fdr = open(direct, O_RDWR)) < 0)
		return -1;
	if (myflock(fdr, LOCK_EX)) {
		close(fdr);
		return -1;
	}

	fhw = tmpfile();
	fdw = fileno(fhw);
	while (myread(fdr, &fhr, FH_SIZE) == FH_SIZE) {
		cmp = cmpfun(fhr.filename, dl[i].fname);
		while (cmp > 0) {
			restore_fileheader(&nfhr, direct, dl[i].fname);
			dbg("Inserted %s\n", dl[i].fname);
			dbg("\tDate: %s User: %s Ident: %d\n",
				nfhr.date, nfhr.owner, nfhr.ident);
			dbg("\tTitle: %s\n", nfhr.title);
			if (mywrite(fdw, &nfhr, FH_SIZE) != FH_SIZE) {
				result = -1;
				break;
			}
			cmp = cmpfun(fhr.filename, dl[++i].fname);
			++result;
		}
		if (cmp == 0) {
			++i;
		} else {
			dbg("Missing %s\n", fhr.filename);
			dbg("\tDate: %s User: %s Ident: %d\n",
				fhr.date, fhr.owner, fhr.ident);
			dbg("\tTitle: %s\n", fhr.title);
		}
		if (mywrite(fdw, &fhr, FH_SIZE) != FH_SIZE) {
			result = -1;
			break;
		}
	}
	if (result > 0)
		result = myfdcp(fdw, fdr);
	fclose(fhw);
	flock(fdr, LOCK_UN);
	close(fdr);
	free(dl);
	return result;
}
Example #8
0
static void restore_fileheader(FILEHEADER *fhr, const char *direct, const char *fname)
{
	time_t t;
	struct tm *tmp;
	char dirpath[PATHLEN], buf[512], *p, *sp, *sp2;
	USEREC urc;

	memset(fhr, 0, sizeof(FILEHEADER));
	if (!fhr || !fname)
		return;

	strcpy(fhr->filename, fname);

	t = strtol(fname + 2, NULL, 10);
	tmp = localtime(&t);
	if (tmp)
		sprintf(fhr->date, "%02d/%02d/%02d",
			tmp->tm_year - 11, tmp->tm_mon + 1, tmp->tm_mday);
	else
		strcpy(fhr->date, "00/00/00");


	setdotfile(dirpath, direct, fname);
	get_record(dirpath, buf, sizeof(buf), 1);
	p = strtok_r(buf,  " ", &sp);
	p = strtok_r(NULL, " ", &sp);
	if (p) {
		strcpy(fhr->owner, p);
		if (!strchr(fhr->owner, '.'))
		{
			if (get_passwd(&urc, fhr->owner) > 0)
				fhr->ident = urc.ident;
		} else {
			p = strtok_r(fhr->owner, "@.", &sp2);
			sprintf(buf, "#%s", p);
			strcpy(fhr->owner, buf);
		}
	} else {
		strcpy(fhr->owner, "UNKNOWN");
	}

	if (sp && (((p = strstr (sp, "標題:")) && (p = p + 5))
		    || ((p = strstr (sp, "標題:")) && (p = p + 6))
		    || ((p = strstr (sp, "標  題:")) && (p = p + 7))
		    || ((p = strstr (sp, "Title:")) && (p = p + 6))
		    || ((p = strstr (sp, "Subject:")) && (p = p + 8)))) {
		while (*p == ' ')
			p++;
		if (*p != '\n')
		{
			strtok (p, "\n");
			strcpy (fhr->title, p);
		}
	} else {
		strcpy(fhr->title, "UNKNOWN");
	}

	if (get_only_postno(direct, 0, fhr) == -1) {
		bbslog("ERROR", "Getting only postno. (%s)", direct);
		fprintf(stderr, "ERROR: Getting only postno. (%s)", direct);
		exit(1);
	}

	/*
	 * Mark readed for bbspop3d
	 */
	if (strstr(direct, "mail"))
		fhr->accessed |= FILE_READ;

}