6a6a253885
Added doc dir. and manual as .pdf restored deleted files - yep I screwed the pooch.
1964 lines
45 KiB
C
1964 lines
45 KiB
C
/*****************************************************************************
|
|
*
|
|
* $Id: file.c,v 1.45 2008/02/12 19:59:45 mbse Exp $
|
|
* Purpose ...............: All the file functions.
|
|
*
|
|
*****************************************************************************
|
|
* Copyright (C) 1997-2008
|
|
*
|
|
* Michiel Broek FIDO: 2:280/2802
|
|
* Beekmansbos 10
|
|
* 1971 BV IJmuiden
|
|
* the Netherlands
|
|
*
|
|
* This file is part of MBSE BBS.
|
|
*
|
|
* This BBS is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2, or (at your option) any
|
|
* later version.
|
|
*
|
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
|
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
|
*****************************************************************************/
|
|
|
|
#include "../config.h"
|
|
#include "../lib/mbselib.h"
|
|
#include "../lib/mbse.h"
|
|
#include "../lib/users.h"
|
|
#include "../lib/mbsedb.h"
|
|
#include "filesub.h"
|
|
#include "file.h"
|
|
#include "funcs.h"
|
|
#include "input.h"
|
|
#include "language.h"
|
|
#include "misc.h"
|
|
#include "timeout.h"
|
|
#include "exitinfo.h"
|
|
#include "whoson.h"
|
|
#include "change.h"
|
|
#include "dispfile.h"
|
|
#include "term.h"
|
|
#include "ttyio.h"
|
|
#include "openport.h"
|
|
#include "transfer.h"
|
|
|
|
|
|
|
|
extern int arecno; /* File area number in xxxScan() functions */
|
|
int Strlen = 0;
|
|
int FileRecno = 0;
|
|
extern int rows;
|
|
extern unsigned int mib_downloads;
|
|
extern unsigned int mib_kbdownload;
|
|
extern unsigned int mib_uploads;
|
|
|
|
|
|
|
|
int CheckFile(char *, int);
|
|
int CheckFile(char *File, int iArea)
|
|
{
|
|
struct _fdbarea *fdb_area = NULL;
|
|
|
|
if ((fdb_area = mbsedb_OpenFDB(iArea, 30)) == NULL)
|
|
return FALSE;
|
|
|
|
/*
|
|
* Check long and short filenames, case insensitive
|
|
*/
|
|
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
|
|
if (((strcasecmp(fdb.Name, File)) == 0) || ((strcasecmp(fdb.LName, File)) == 0)) {
|
|
mbsedb_CloseFDB(fdb_area);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
mbsedb_CloseFDB(fdb_area);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Show filelist from current area, called from the menu.
|
|
*/
|
|
void File_List()
|
|
{
|
|
int FileCount = 0;
|
|
unsigned FileBytes = 0;
|
|
_Tag T;
|
|
struct _fdbarea *fdb_area = NULL;
|
|
char temp[81];
|
|
|
|
iLineCount = 0;
|
|
WhosDoingWhat(FILELIST, NULL);
|
|
|
|
Syslog('+', "Listing File Area # %d", iAreaNumber);
|
|
|
|
if (Access(exitinfo.Security, area.LTSec) == FALSE) {
|
|
Enter(1);
|
|
/* You don't have enough security to list this area */
|
|
pout(YELLOW, BLACK, (char *) Language(236));
|
|
Enter(2);
|
|
Pause();
|
|
return;
|
|
}
|
|
|
|
InitTag();
|
|
|
|
if ((fdb_area = mbsedb_OpenFDB(iAreaNumber, 30)) == NULL)
|
|
return;
|
|
|
|
if (utf8)
|
|
chartran_init((char *)"CP437", (char *)"UTF-8", 'b');
|
|
|
|
clear();
|
|
Header();
|
|
if (iLC(2) == 1) {
|
|
mbsedb_CloseFDB(fdb_area);
|
|
chartran_close();
|
|
return;
|
|
}
|
|
|
|
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
|
|
memset(&T, 0, sizeof(T));
|
|
T.Area = iAreaNumber;
|
|
T.Active = FALSE;
|
|
T.Size = fdb.Size;
|
|
strncpy(T.SFile, fdb.Name, 12);
|
|
strncpy(T.LFile, chartran(fdb.LName), 80);
|
|
SetTag(T);
|
|
|
|
if (ShowOneFile() == 1) {
|
|
mbsedb_CloseFDB(fdb_area);
|
|
chartran_close();
|
|
return;
|
|
}
|
|
|
|
if (fdb.Deleted) {
|
|
/* D E L E T E D */ /* Uploaded by: */
|
|
snprintf(temp, 81, " -- %-12s %s [%4d] %s%s\n", fdb.Name, (char *) Language(239),
|
|
fdb.TimesDL, (char *) Language(238), fdb.Uploader);
|
|
PUTSTR(temp);
|
|
}
|
|
|
|
FileCount++; /* Increase File Counter by 1 */
|
|
FileBytes += fdb.Size; /* Increase File Byte Count */
|
|
}
|
|
|
|
Mark();
|
|
|
|
Enter(1);
|
|
/* Total Files: */
|
|
snprintf(temp, 81, "%s%d / %d bytes", (char *) Language(242), FileCount, FileBytes);
|
|
pout(LIGHTCYAN, BLACK, temp);
|
|
Enter(2);
|
|
chartran_close();
|
|
|
|
iLineCount = 0;
|
|
mbsedb_CloseFDB(fdb_area);
|
|
Pause();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Download files already tagged, called from the menu.
|
|
*/
|
|
void Download(void)
|
|
{
|
|
FILE *tf, *fd;
|
|
int rc = 0, i, Count = 0, OldArea;
|
|
char *local, *temp;
|
|
int Size = 0, CostSize = 0, dsize;
|
|
struct _fdbarea *fdb_area = NULL;
|
|
down_list *dl = NULL, *tmpf;
|
|
|
|
Enter(2);
|
|
OldArea = iAreaNumber;
|
|
WhosDoingWhat(DOWNLOAD, NULL);
|
|
|
|
/*
|
|
* Clean users tag directory.
|
|
*/
|
|
temp = calloc(PATH_MAX, sizeof(char));
|
|
snprintf(temp, PATH_MAX, "-rf %s/%s/tag", CFG.bbs_usersdir, exitinfo.Name);
|
|
execute_pth((char *)"rm", temp, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null");
|
|
snprintf(temp, PATH_MAX, "%s/%s/tag", CFG.bbs_usersdir, exitinfo.Name);
|
|
CheckDir(temp);
|
|
|
|
if ((tf = fopen("taglist", "r+")) == NULL) {
|
|
Syslog('+', "Download command but no files marked");
|
|
/* No files marked for download. */
|
|
pout(LIGHTRED, BLACK, (char *) Language(258));
|
|
Enter(2);
|
|
Pause();
|
|
return;
|
|
}
|
|
|
|
local = calloc(PATH_MAX, sizeof(char));
|
|
/* Checking your marked downloads, please wait... */
|
|
pout(LIGHTMAGENTA, BLACK, (char *) Language(255));
|
|
Enter(2);
|
|
|
|
ReadExitinfo();
|
|
while (fread(&Tag, sizeof(Tag), 1, tf) == 1) {
|
|
if (Tag.Active) {
|
|
|
|
SetFileArea(Tag.Area);
|
|
|
|
/*
|
|
* Check password for selected file FIXME: Where???
|
|
*/
|
|
memset(&fdb, 0, sizeof(fdb));
|
|
if ((fdb_area = mbsedb_OpenFDB(Tag.Area, 30)) != NULL) {
|
|
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
|
|
if (strcmp(fdb.LName, Tag.LFile) == 0)
|
|
break;
|
|
}
|
|
mbsedb_CloseFDB(fdb_area);
|
|
}
|
|
|
|
if (strcmp(fdb.LName, Tag.LFile) == 0) {
|
|
Syslog('b', "Found file %s in area %d", fdb.LName, Tag.Area);
|
|
if (fdb.Deleted) {
|
|
/* Sorry that file is unavailable for download */
|
|
snprintf(temp, 81, "%s (%s)", (char *) Language(248), fdb.LName);
|
|
poutCR(CFG.HiliteF, CFG.HiliteB, temp);
|
|
Tag.Active = FALSE;
|
|
Syslog('+', "File %s in area %d unavailable for download, deleted", fdb.LName, Tag.Area);
|
|
}
|
|
}
|
|
|
|
if (Tag.Active) {
|
|
/*
|
|
* Create/Append file description list while we're
|
|
* busy checking. If the users doesn't want it we
|
|
* can unlink it aftwerwards. We also insert CR
|
|
* characters to please the poor DOS (M$oft) users.
|
|
*/
|
|
snprintf(local, PATH_MAX, "./tag/filedesc.%d", exitinfo.Downloads % 256);
|
|
if ((fd = fopen(local, "a")) != NULL) {
|
|
fprintf(fd, "%s (%s)\r\n", fdb.LName, fdb.Name);
|
|
for (i = 0; i < 25; i++) {
|
|
if (strlen(fdb.Desc[i]) > 1)
|
|
fprintf(fd, " %s\r\n", fdb.Desc[i]);
|
|
}
|
|
fprintf(fd, "\r\n");
|
|
fclose(fd);
|
|
Syslog('b', "Added info to %s", local);
|
|
} else {
|
|
WriteError("Can't add info to %s", local);
|
|
}
|
|
|
|
snprintf(local, PATH_MAX, "%s/%s", sAreaPath, Tag.LFile);
|
|
add_download(&dl, local, Tag.LFile, Tag.Area, fdb.Size, FALSE);
|
|
|
|
Home();
|
|
}
|
|
|
|
if (!Tag.Active) {
|
|
/*
|
|
* Update the download active flag in the
|
|
* taglist
|
|
*/
|
|
fseek(tf, - sizeof(Tag), SEEK_CUR);
|
|
fwrite(&Tag, sizeof(Tag), 1, tf);
|
|
Syslog('b', "Download file %s marked inactive in taglist", Tag.LFile);
|
|
} else {
|
|
/*
|
|
* Count file and sizes.
|
|
*/
|
|
Count++;
|
|
Size += fdb.Size;
|
|
if (!area.Free)
|
|
CostSize += fdb.Size;
|
|
}
|
|
}
|
|
}
|
|
fclose(tf);
|
|
|
|
/*
|
|
* If anything left to download...
|
|
*/
|
|
if (!Count) {
|
|
SetFileArea(OldArea);
|
|
unlink("taglist");
|
|
/* No files marked for download */
|
|
pout(LIGHTRED, BLACK, (char *) Language(258));
|
|
Enter(2);
|
|
Pause();
|
|
free(temp);
|
|
free(local);
|
|
tidy_download(&dl);
|
|
Syslog('+', "No files left to download");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Add descriptions file to the queue.
|
|
*/
|
|
snprintf(local, PATH_MAX, "%s/%s/tag/filedesc.%d", CFG.bbs_usersdir, exitinfo.Name, exitinfo.Downloads % 256);
|
|
dsize = file_size(local);
|
|
snprintf(temp, PATH_MAX, "filedesc.%d", exitinfo.Downloads % 256);
|
|
add_download(&dl, local, temp, 0, dsize, TRUE);
|
|
free(local);
|
|
|
|
/* You have */ /* files( */ /* bytes) marked for download */
|
|
snprintf(temp, PATH_MAX, "%s %d %s%d %s", (char *) Language(249), Count, (char *) Language(280), Size, (char *) Language(281));
|
|
pout(YELLOW, BLACK, temp);
|
|
Enter(2);
|
|
|
|
if (!CheckBytesAvailable(CostSize)) {
|
|
SetFileArea(OldArea);
|
|
free(temp);
|
|
tidy_download(&dl);
|
|
return;
|
|
}
|
|
|
|
Pause();
|
|
|
|
if ((rc = download(dl))) {
|
|
/*
|
|
* Download error
|
|
*/
|
|
Syslog('+', "Download error rc=%d", rc);
|
|
free(temp);
|
|
tidy_download(&dl);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Checking the successfull sent files, they are missing from
|
|
* the ./tag directory. Failed files are still there.
|
|
*/
|
|
PUTCHAR('\r');
|
|
/* Updating download counters, please wait ... */
|
|
pout(LIGHTCYAN, BLACK, (char *) Language(352));
|
|
Count = Size = 0;
|
|
|
|
/*
|
|
* Update downloadcounters, don't log anything because the state
|
|
* of sucessfull sent files is already logged by the download
|
|
* function.
|
|
*/
|
|
if ((tf = fopen("taglist", "r+")) != NULL) {
|
|
while (fread(&Tag, sizeof(Tag), 1, tf) == 1) {
|
|
PUTCHAR('.');
|
|
if (Tag.Active) {
|
|
for (tmpf = dl; tmpf; tmpf = tmpf->next) {
|
|
if (strcmp(tmpf->remote, Tag.LFile) == 0) {
|
|
if (tmpf->sent) {
|
|
|
|
Tag.Active = FALSE;
|
|
fseek(tf, - sizeof(Tag), SEEK_CUR);
|
|
fwrite(&Tag, sizeof(Tag), 1, tf);
|
|
|
|
/*
|
|
* Update the download counter and the last download date.
|
|
*/
|
|
SetFileArea(Tag.Area);
|
|
if ((fdb_area = mbsedb_OpenFDB(Tag.Area, 30))) {
|
|
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
|
|
if (strcmp(fdb.LName, Tag.LFile) == 0)
|
|
break;
|
|
}
|
|
Size += fdb.Size;
|
|
fdb.TimesDL++;
|
|
fdb.LastDL = time(NULL);
|
|
if (mbsedb_LockFDB(fdb_area, 30)) {
|
|
fseek(fdb_area->fp, - fdbhdr.recsize, SEEK_CUR);
|
|
fwrite(&fdb, fdbhdr.recsize, 1, fdb_area->fp);
|
|
mbsedb_UnlockFDB(fdb_area);
|
|
}
|
|
mbsedb_CloseFDB(fdb_area);
|
|
Count++;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fclose(tf);
|
|
}
|
|
Enter(2);
|
|
|
|
/*
|
|
* Update the users record.
|
|
*/
|
|
ReadExitinfo();
|
|
|
|
exitinfo.Downloads += Count; /* Increase download counter */
|
|
mib_downloads += Count;
|
|
exitinfo.DownloadK += (Size / 1024); /* Increase amount download today */
|
|
mib_kbdownload += (Size / 1024);
|
|
|
|
/*
|
|
* Minus the amount downloaded today from downloadktoday
|
|
* if less than zero, it won't let the user download anymore.
|
|
*/
|
|
if (LIMIT.DownK || LIMIT.DownF) {
|
|
exitinfo.DownloadKToday -= (Size / 1024);
|
|
}
|
|
|
|
WriteExitinfo();
|
|
Pause();
|
|
SetFileArea(OldArea);
|
|
free(temp);
|
|
tidy_download(&dl);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Show Raw directory
|
|
*/
|
|
void File_RawDir(char *OpData)
|
|
{
|
|
DIR *dirp;
|
|
char *FileName, *temp, temp2[81];
|
|
int iFileCount = 0, LineCount = 2, iBytes = 0;
|
|
struct dirent *dp;
|
|
struct stat statfile;
|
|
|
|
FileName = calloc(PATH_MAX, sizeof(char));
|
|
temp = calloc(PATH_MAX, sizeof(char));
|
|
|
|
if ((strcmp(OpData, "/F")) == 0)
|
|
strcpy(temp, sAreaPath);
|
|
else
|
|
strcpy(temp, OpData);
|
|
|
|
if ((dirp = opendir(temp)) == NULL) {
|
|
clear();
|
|
WriteError("$RawDir: Can't open dir: %s", temp);
|
|
Enter(1);
|
|
pout(LIGHTRED, BLACK, (char *)"Can't open directory for raw listing!");
|
|
Enter(2);
|
|
Pause();
|
|
} else {
|
|
if (utf8)
|
|
chartran_init((char *)"CP437", (char *)"UTF-8", 'b');
|
|
|
|
clear();
|
|
/* Filename Size Date */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(261));
|
|
Enter(1);
|
|
PUTSTR(chartran(fLine_str(78)));
|
|
|
|
while ((dp = readdir( dirp )) != NULL ) {
|
|
snprintf(FileName, PATH_MAX, "%s/%s", temp, dp->d_name);
|
|
|
|
if (*(dp->d_name) != '.') {
|
|
iFileCount++;
|
|
if (stat(FileName, &statfile) != 0) {
|
|
pout(LIGHTRED, BLACK, (char *)"Can't stat file ");
|
|
PUTSTR(FileName);
|
|
} else {
|
|
iBytes += statfile.st_size;
|
|
|
|
snprintf(temp2, 81, "%-54s " , dp->d_name);
|
|
pout(YELLOW, BLACK, temp2);
|
|
|
|
snprintf(temp2, 81, "%-12d", (int)(statfile.st_size));
|
|
pout(LIGHTMAGENTA, BLACK, temp2);
|
|
|
|
snprintf(temp2, 81, "%-10s", StrDateDMY(statfile.st_mtime));
|
|
pout(LIGHTGREEN, BLACK, temp2);
|
|
}
|
|
Enter(1);
|
|
|
|
LineCount++;
|
|
if (LineCount == rows) {
|
|
Pause();
|
|
LineCount = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
colour(CFG.HiliteF, CFG.HiliteB);
|
|
PUTSTR(chartran(fLine_str(78)));
|
|
/* Total Files: */ /* Bytes */
|
|
snprintf(temp2, 81, "%s %d, %d %s", (char *) Language(242), iFileCount, iBytes, (char *) Language(354));
|
|
pout(LIGHTGREEN, BLACK, temp2);
|
|
Enter(2);
|
|
|
|
Pause();
|
|
closedir(dirp);
|
|
chartran_close();
|
|
}
|
|
|
|
free(temp);
|
|
free(FileName);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Search for keyword, called from menu.
|
|
*/
|
|
int KeywordScan()
|
|
{
|
|
FILE *pAreas;
|
|
int i, z, y, Found, Count = 0;
|
|
char *Name, *tmpname, *BigDesc, temp[81];
|
|
_Tag T;
|
|
unsigned int OldArea;
|
|
struct _fdbarea *fdb_area = NULL;
|
|
|
|
Name = calloc(81, sizeof(char));
|
|
tmpname = calloc(81, sizeof(char));
|
|
BigDesc = calloc(1230, sizeof(char));
|
|
OldArea = iAreaNumber;
|
|
|
|
iLineCount = 2; /* Reset Line Counter to Zero */
|
|
arecno = 1; /* Reset Area Number to One */
|
|
|
|
Enter(2);
|
|
/* Enter keyword to use for Search: */
|
|
pout(LIGHTCYAN, BLACK, (char *) Language(267));
|
|
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
GetstrC(Name, 80);
|
|
|
|
if ((strcmp(Name, "")) == 0)
|
|
return 0;
|
|
|
|
strcpy(tmpname, tl(Name));
|
|
strcpy(Name, "");
|
|
y = strlen(tmpname);
|
|
for (z = 0; z < y; z++) {
|
|
if (tmpname[z] != '*') {
|
|
snprintf(temp, 81, "%c", tmpname[z]);
|
|
strcat(Name, temp);
|
|
}
|
|
}
|
|
Syslog('+', "KeywordScan(): \"%s\"", Name);
|
|
|
|
clear();
|
|
/* File search by keyword */
|
|
pout(WHITE, BLACK, (char *) Language(268));
|
|
Enter(1);
|
|
InitTag();
|
|
|
|
if ((pAreas = OpenFareas(FALSE)) == NULL)
|
|
return 0;
|
|
|
|
while (fread(&area, areahdr.recsize, 1, pAreas) == 1) {
|
|
|
|
if ((Access(exitinfo.Security, area.LTSec)) && (area.Available) && (strlen(area.Password) == 0)) {
|
|
|
|
if ((fdb_area = mbsedb_OpenFDB(arecno, 30))) {
|
|
Nopper();
|
|
Found = FALSE;
|
|
Sheader();
|
|
|
|
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
|
|
for (i = 0; i < 25; i++)
|
|
snprintf(BigDesc, 1230, "%s%s", BigDesc, *(fdb.Desc + i));
|
|
|
|
if ((strstr(fdb.Name,Name) != NULL) || (strstr(tl(BigDesc), Name) != NULL)) {
|
|
|
|
if (!Found) {
|
|
Enter(2);
|
|
if (iLC(2) == 1) {
|
|
free(BigDesc);
|
|
free(Name);
|
|
free(tmpname);
|
|
SetFileArea(OldArea);
|
|
return 1;
|
|
}
|
|
Found = TRUE;
|
|
}
|
|
|
|
memset(&T, 0, sizeof(T));
|
|
T.Area = arecno;
|
|
T.Active = FALSE;
|
|
T.Size = fdb.Size;
|
|
strncpy(T.SFile, fdb.Name, 12);
|
|
strncpy(T.LFile, fdb.LName, 80);
|
|
SetTag(T);
|
|
Count++;
|
|
if (ShowOneFile() == 1) {
|
|
free(BigDesc);
|
|
free(Name);
|
|
free(tmpname);
|
|
SetFileArea(OldArea);
|
|
return 1;
|
|
}
|
|
}
|
|
strcpy(BigDesc, ""); /* Clear BigDesc */
|
|
|
|
} /* while */
|
|
|
|
mbsedb_CloseFDB(fdb_area);
|
|
if (Found) {
|
|
Enter(2);
|
|
if (iLC(2) == 1) {
|
|
free(BigDesc);
|
|
free(Name);
|
|
free(tmpname);
|
|
SetFileArea(OldArea);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
} /* End check for LTSec */
|
|
} /* if access */
|
|
arecno++; /* Go to next file area */
|
|
} /* End of Main */
|
|
|
|
Syslog('+', "Found %d files", Count);
|
|
free(BigDesc);
|
|
free(Name);
|
|
free(tmpname);
|
|
fclose(pAreas);
|
|
Enter(1);
|
|
if (Count)
|
|
Mark();
|
|
else
|
|
Pause();
|
|
SetFileArea(OldArea);
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Search for a file, called from the menu.
|
|
*/
|
|
int FilenameScan()
|
|
{
|
|
FILE *pAreas;
|
|
int Found, Count = 0;
|
|
char mask[256];
|
|
char *Name;
|
|
_Tag T;
|
|
unsigned int OldArea;
|
|
struct _fdbarea *fdb_area = NULL;
|
|
|
|
Name = calloc(81, sizeof(char));
|
|
OldArea = iAreaNumber;
|
|
|
|
iLineCount = 2; /* Reset Line Counter to Zero */
|
|
arecno = 1; /* Reset Area Number to One */
|
|
|
|
Enter(2);
|
|
/* Accepts wildcards such as : *.zip, *.gz, *.* */
|
|
pout(WHITE, BLACK, (char *) Language(269));
|
|
|
|
Enter(2);
|
|
/* Enter filename to search for : */
|
|
pout(LIGHTCYAN, BLACK, (char *) Language(271));
|
|
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
GetstrC(Name, 80);
|
|
|
|
if ((strcmp(Name, "")) == 0) {
|
|
free(Name);
|
|
return 0;
|
|
}
|
|
|
|
strcpy(mask, re_mask(Name, TRUE));
|
|
Syslog('+', "FilenameScan(): \"%s\" -> \"%s\"", Name, mask);
|
|
free(Name);
|
|
re_comp(mask);
|
|
|
|
clear();
|
|
/* File Search by Filename */
|
|
pout(WHITE, BLACK, (char *) Language(272));
|
|
Enter(1);
|
|
InitTag();
|
|
|
|
if ((pAreas = OpenFareas(FALSE)) == NULL)
|
|
return 0;
|
|
|
|
while (fread(&area, areahdr.recsize, 1, pAreas) == 1) {
|
|
if ((Access(exitinfo.Security, area.LTSec)) && (area.Available) && (strlen(area.Password) == 0)) {
|
|
|
|
if ((fdb_area = mbsedb_OpenFDB(arecno, 30))) {
|
|
Found = FALSE;
|
|
Sheader();
|
|
Nopper();
|
|
|
|
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
|
|
if (re_exec(fdb.Name) || re_exec(fdb.LName)) {
|
|
if (!Found) {
|
|
Enter(2);
|
|
if (iLC(2) == 1) {
|
|
SetFileArea(OldArea);
|
|
return 1;
|
|
}
|
|
Found = TRUE;
|
|
}
|
|
|
|
memset(&T, 0, sizeof(T));
|
|
T.Area = arecno;
|
|
T.Active = FALSE;
|
|
T.Size = fdb.Size;
|
|
strncpy(T.SFile, fdb.Name, 12);
|
|
strncpy(T.LFile, fdb.LName, 81);
|
|
SetTag(T);
|
|
Count++;
|
|
if (ShowOneFile() == 1) {
|
|
SetFileArea(OldArea);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
} /* End of while */
|
|
|
|
mbsedb_CloseFDB(fdb_area);
|
|
if (Found) {
|
|
Enter(2);
|
|
if (iLC(2) == 1) {
|
|
SetFileArea(OldArea);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
} /* End Check for LTSec */
|
|
} /* if access */
|
|
arecno++; /* Go to next file area */
|
|
|
|
} /* End of Main */
|
|
|
|
Syslog('+', "Found %d files", Count);
|
|
fclose(pAreas);
|
|
Enter(1);
|
|
if (Count)
|
|
Mark();
|
|
else
|
|
Pause();
|
|
SetFileArea(OldArea);
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Scan for new files, called from menu.
|
|
*/
|
|
int NewfileScan(int AskStart)
|
|
{
|
|
FILE *pAreas;
|
|
int ifDate, itDate;
|
|
char *temp, *Date;
|
|
int Found, Count = 0;
|
|
_Tag T;
|
|
struct _fdbarea *fdb_area = NULL;
|
|
|
|
Date = calloc(81, sizeof(char));
|
|
temp = calloc(81, sizeof(char));
|
|
|
|
iLineCount = 2;
|
|
arecno = 1; /* Reset Area Number to One */
|
|
|
|
if (AskStart) {
|
|
Enter(2);
|
|
/* Search for new since your last call [Y/n]: */
|
|
pout(LIGHTCYAN, BLACK, (char *) Language(273));
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
|
|
if (toupper(Readkey()) == Keystroke(273, 1)) {
|
|
Enter(1);
|
|
/* Enter new date to search for [DD-MM-YYYY]: */
|
|
pout(GREEN, BLACK, (char *) Language(274));
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
GetDate(temp, 10);
|
|
} else {
|
|
strcpy(temp, LastLoginDate);
|
|
}
|
|
} else {
|
|
strcpy(temp, LastLoginDate);
|
|
}
|
|
|
|
Syslog('+', "NewfileScan() since %s", temp);
|
|
clear();
|
|
/* File Search by Date */
|
|
pout(WHITE, BLACK, (char *) Language(275));
|
|
Enter(2);
|
|
|
|
Date[0] = temp[6]; /* Swap the date around */
|
|
Date[1] = temp[7]; /* Instead of DD-MM-YYYY */
|
|
Date[2] = temp[8]; /* Let it equal YYYYMMDD */
|
|
Date[3] = temp[9]; /* Swap the date around */
|
|
Date[4] = temp[3]; /* Swap the date around */
|
|
Date[5] = temp[4]; /* because when you convert */
|
|
Date[6] = temp[0]; /* a string to an int you */
|
|
Date[7] = temp[1]; /* loose the front Zero */
|
|
Date[8] = '\0'; /* making the number smaller */
|
|
itDate = atol(Date);
|
|
|
|
InitTag();
|
|
|
|
if ((pAreas = OpenFareas(FALSE)) == NULL)
|
|
return 0;
|
|
|
|
while (fread(&area, areahdr.recsize, 1, pAreas) == 1) {
|
|
|
|
if ((Access(exitinfo.Security, area.LTSec)) && (area.Available) && (strlen(area.Password) == 0) && (area.New)) {
|
|
|
|
if ((fdb_area = mbsedb_OpenFDB(arecno, 30))) {
|
|
Sheader();
|
|
Found = FALSE;
|
|
Nopper();
|
|
|
|
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
|
|
strcpy(temp, StrDateDMY(fdb.UploadDate)); /* Realloc Space for Date */
|
|
Date[0] = temp[6]; /* Swap the date around */
|
|
Date[1] = temp[7]; /* Instead of DD-MM-YYYY */
|
|
Date[2] = temp[8]; /* Let it equal YYYYMMDD */
|
|
Date[3] = temp[9]; /* Swap the date around */
|
|
Date[4] = temp[3]; /* Swap the date around */
|
|
Date[5] = temp[4]; /* because when you convert */
|
|
Date[6] = temp[0]; /* a string to an int you */
|
|
Date[7] = temp[1]; /* loose the front Zero */
|
|
Date[8] = '\0'; /* making the number smaller */
|
|
/* and invalid to this cause */
|
|
ifDate = atol(Date);
|
|
|
|
if (ifDate >= itDate) {
|
|
if (!Found) {
|
|
Enter(2);
|
|
if (iLC(2) == 1) {
|
|
free(Date);
|
|
free(temp);
|
|
mbsedb_CloseFDB(fdb_area);
|
|
fclose(pAreas);
|
|
return 1;
|
|
}
|
|
Found = TRUE;
|
|
}
|
|
|
|
memset(&T, 0, sizeof(T));
|
|
T.Area = arecno;
|
|
T.Active = FALSE;
|
|
T.Size = fdb.Size;
|
|
strncpy(T.SFile, fdb.Name, 12);
|
|
strncpy(T.LFile, fdb.LName, 80);
|
|
SetTag(T);
|
|
|
|
Count++;
|
|
if (ShowOneFile() == 1) {
|
|
free(Date);
|
|
free(temp);
|
|
mbsedb_CloseFDB(fdb_area);
|
|
fclose(pAreas);
|
|
return 1;
|
|
}
|
|
} /* End of if */
|
|
} /* End of while */
|
|
|
|
mbsedb_CloseFDB(fdb_area);
|
|
|
|
/*
|
|
* Add 2 blank lines after found files.
|
|
*/
|
|
if (Found) {
|
|
Enter(2);
|
|
if (iLC(2) == 1) {
|
|
free(Date);
|
|
free(temp);
|
|
fclose(pAreas);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
} /* End of open filebase */
|
|
|
|
} /* End of check new files scan */
|
|
arecno++; /* Go to next file area */
|
|
} /* End of Main */
|
|
|
|
if (Count)
|
|
Syslog('+', "Found %d new files", Count);
|
|
fclose(pAreas);
|
|
Enter(1);
|
|
if (Count)
|
|
Mark();
|
|
else
|
|
Pause();
|
|
|
|
free(temp);
|
|
free(Date);
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Upload a file.
|
|
*/
|
|
int Upload()
|
|
{
|
|
int Area, rc;
|
|
unsigned int OldArea;
|
|
char *arc, *temp;
|
|
up_list *up = NULL, *tmpf;
|
|
|
|
WhosDoingWhat(UPLOAD, NULL);
|
|
Enter(1);
|
|
Area = OldArea = iAreaNumber;
|
|
|
|
/*
|
|
* If there is a special upload area for the current area
|
|
* then select it.
|
|
*/
|
|
if (area.Upload)
|
|
Area = area.Upload;
|
|
SetFileArea(Area);
|
|
Syslog('+', "Upload area is %d %s", Area, area.Name);
|
|
|
|
/*
|
|
* Check upload access for the real upload directory.
|
|
*/
|
|
if (!Access(exitinfo.Security, area.UPSec)) {
|
|
Enter(1);
|
|
/* You do not have enough access to upload to this area */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(278));
|
|
Enter(2);
|
|
SetFileArea(OldArea);
|
|
Pause();
|
|
return 0;
|
|
}
|
|
|
|
clear();
|
|
Enter(2);
|
|
|
|
rc = upload(&up);
|
|
|
|
if (rc) {
|
|
Syslog('+', "Upload failed, rc=%d", rc);
|
|
SetFileArea(OldArea);
|
|
return 0;
|
|
}
|
|
Syslog('b', "upload done, start checks");
|
|
|
|
Enter(2);
|
|
pout(CFG.UnderlineColourF, CFG.UnderlineColourB, (char *)"Checking your upload(s)");
|
|
Enter(1);
|
|
|
|
temp = calloc(PATH_MAX, sizeof(char));
|
|
for (tmpf = up; tmpf; tmpf = tmpf->next) {
|
|
snprintf(temp, PATH_MAX, "%s/%s/upl", CFG.bbs_usersdir, exitinfo.Name);
|
|
chdir(temp);
|
|
|
|
Syslog('b', "Checking upload %s", tmpf->filename);
|
|
if ((arc = GetFileType(tmpf->filename)) == NULL) {
|
|
/*
|
|
* If the filetype is unknown, it is probably
|
|
* a textfile or so. Import it direct.
|
|
*/
|
|
Syslog('b', "Unknown file type");
|
|
if (!ScanDirect(basename(tmpf->filename)))
|
|
ImportFile(tmpf->filename, Area, FALSE, tmpf->size);
|
|
} else {
|
|
/*
|
|
* We figured out the type of the uploaded file.
|
|
*/
|
|
Syslog('b', "File type is %s", arc);
|
|
|
|
/*
|
|
* MS-DOS executables are handled direct.
|
|
*/
|
|
if ((strcmp("EXE", arc) == 0) || (strcmp("COM", arc) == 0)) {
|
|
if (!ScanDirect(basename(tmpf->filename)))
|
|
ImportFile(tmpf->filename, Area, FALSE, tmpf->size);
|
|
} else {
|
|
switch (ScanArchive(basename(tmpf->filename), arc)) {
|
|
case 0: ImportFile(tmpf->filename, Area, TRUE, tmpf->size);
|
|
break;
|
|
case 1: break;
|
|
case 2: break;
|
|
case 3: /*
|
|
* No valid unarchiver found, just import after scanning,
|
|
* may catch macro viri.
|
|
*/
|
|
if (!ScanDirect(basename(tmpf->filename)))
|
|
ImportFile(tmpf->filename, Area, FALSE, tmpf->size);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tidy_upload(&up);
|
|
free(temp);
|
|
Home();
|
|
SetFileArea(OldArea);
|
|
Pause();
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Function will download a specific file
|
|
*/
|
|
int DownloadDirect(char *Name, int Wait)
|
|
{
|
|
int rc = 0;
|
|
int Size;
|
|
down_list *dl = NULL;
|
|
|
|
if ((Size = file_size(Name)) == -1) {
|
|
WriteError("No file %s", Name);
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *)"File not found");
|
|
Enter(2);
|
|
Pause();
|
|
}
|
|
|
|
Syslog('+', "Download direct %s", Name);
|
|
|
|
add_download(&dl, Name, basename(Name), 0, Size, FALSE);
|
|
WhosDoingWhat(DOWNLOAD, NULL);
|
|
|
|
if ((rc = download(dl))) {
|
|
/*
|
|
* Error
|
|
*/
|
|
Syslog('+', "Download failed rc=%d", rc);
|
|
poutCR(LIGHTRED, BLACK, (char *)Language(353));
|
|
} else {
|
|
/*
|
|
* Update the users record. The file is free, so only statistics.
|
|
*/
|
|
ReadExitinfo();
|
|
exitinfo.Downloads++; /* Increase download counter */
|
|
mib_downloads++;
|
|
WriteExitinfo();
|
|
}
|
|
|
|
if (Wait)
|
|
Pause();
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Function will list users home directory
|
|
*/
|
|
void List_Home()
|
|
{
|
|
DIR *dirp;
|
|
char *FileName, *temp;
|
|
int iFileCount = 0, iBytes = 0;
|
|
struct dirent *dp;
|
|
struct stat statfile;
|
|
|
|
FileName = calloc(PATH_MAX, sizeof(char));
|
|
temp = calloc(PATH_MAX, sizeof(char));
|
|
|
|
iLineCount = 2;
|
|
clear();
|
|
snprintf(temp, PATH_MAX, "%s/%s/wrk", CFG.bbs_usersdir, exitinfo.Name);
|
|
|
|
if ((dirp = opendir(temp)) == NULL) {
|
|
WriteError("$List_Home: Can't open dir: %s", temp);
|
|
Enter(1);
|
|
/* Can't open directory for listing: */
|
|
pout(LIGHTRED, BLACK, (char *) Language(290));
|
|
Enter(2);
|
|
Pause();
|
|
} else {
|
|
/* Home directory listing for */
|
|
snprintf(temp, 81, " %s", (char *) Language(291));
|
|
pout(BLUE, LIGHTGRAY, temp);
|
|
snprintf(temp, 81, "%-51s", exitinfo.sUserName);
|
|
pout(RED, LIGHTGRAY, temp);
|
|
Enter(1);
|
|
|
|
while ((dp = readdir( dirp )) != NULL ) {
|
|
snprintf(temp, PATH_MAX, "%s/%s/wrk", CFG.bbs_usersdir, exitinfo.Name);
|
|
snprintf(FileName, PATH_MAX, "%s/%s", temp, dp->d_name);
|
|
/*
|
|
* Check first letter of file for a ".", do not display hidden files
|
|
* This includes the current directory and parent directory . & ..
|
|
*/
|
|
if (*(dp->d_name) != '.') {
|
|
iFileCount++;
|
|
if (stat(FileName, &statfile) != 0) {
|
|
WriteError("$Can't stat file %s",FileName);
|
|
} else {
|
|
iBytes += statfile.st_size;
|
|
snprintf(temp, 81, "%-20s", dp->d_name);
|
|
pout(YELLOW, BLACK, temp);
|
|
snprintf(temp, 81, "%-12d", (int)(statfile.st_size));
|
|
pout(LIGHTMAGENTA, BLACK, temp);
|
|
snprintf(temp, 81, "%s ", StrDateDMY(statfile.st_mtime));
|
|
pout(LIGHTGREEN, BLACK, temp);
|
|
snprintf(temp, 81, "%s", StrTimeHMS(statfile.st_mtime));
|
|
pout(LIGHTCYAN, BLACK, temp);
|
|
Enter(1);
|
|
}
|
|
}
|
|
if (iLC(1) == 1)
|
|
return;
|
|
}
|
|
|
|
Enter(2);
|
|
/* Total Files: */ /* Bytes */
|
|
snprintf(temp, 81, "%s%d / %d %s", (char *) Language(242), iFileCount, iBytes, (char *) Language(354));
|
|
pout(LIGHTCYAN, BLACK, temp);
|
|
Enter(1);
|
|
Pause();
|
|
closedir(dirp);
|
|
}
|
|
|
|
free(temp);
|
|
free(FileName);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Delete files from home directory
|
|
*/
|
|
void Delete_Home()
|
|
{
|
|
char *temp, *temp1, msg[81];
|
|
int i;
|
|
|
|
temp = calloc(PATH_MAX, sizeof(char));
|
|
temp1 = calloc(PATH_MAX, sizeof(char));
|
|
|
|
snprintf(temp, PATH_MAX, "%s/%s/wrk/", CFG.bbs_usersdir, exitinfo.Name);
|
|
|
|
Enter(1);
|
|
/* Please enter filename to delete: */
|
|
pout(LIGHTBLUE, BLACK, (char *) Language(292));
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
GetstrC(temp1, 80);
|
|
|
|
if (strcmp(temp1, "") == 0) {
|
|
free(temp);
|
|
free(temp1);
|
|
return;
|
|
}
|
|
|
|
if (temp1[0] == '.') {
|
|
Enter(1);
|
|
/* Sorry you may not delete hidden files ...*/
|
|
pout(LIGHTRED, BLACK, (char *) Language(293));
|
|
} else {
|
|
strcat(temp, temp1);
|
|
|
|
if ((access(temp, R_OK)) == 0) {
|
|
Enter(1);
|
|
/* Delete file: */ /* Are you Sure? [Y/n]: */
|
|
snprintf(msg, 81, "%s %s, %s", (char *) Language(368), temp1, (char *) Language(369));
|
|
pout(LIGHTGREEN, BLACK, msg);
|
|
i = toupper(Readkey());
|
|
|
|
if (i == Keystroke(369, 0) || i == 13) {
|
|
i = unlink(temp);
|
|
|
|
if (i == -1) {
|
|
Enter(1);
|
|
/* Unable to delete file ... */
|
|
pout(LIGHTRED, BLACK, (char *) Language(294));
|
|
} else {
|
|
Syslog('+', "Delete %s from homedir", temp1);
|
|
}
|
|
} else {
|
|
Enter(2);
|
|
/* Aborting ... */
|
|
pout(DARKGRAY, BLACK, (char *) Language(116));
|
|
}
|
|
} else {
|
|
Enter(1);
|
|
/* Invalid filename, please try again ... */
|
|
pout(LIGHTRED, BLACK, (char *) Language(295));
|
|
}
|
|
|
|
}
|
|
|
|
Enter(2);
|
|
free(temp);
|
|
free(temp1);
|
|
Pause();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Function allows user to download from his/her home directory
|
|
* but still does all the necessary checks
|
|
*/
|
|
int Download_Home()
|
|
{
|
|
char *temp, *File;
|
|
struct stat statfile;
|
|
int rc;
|
|
|
|
File = calloc(PATH_MAX, sizeof(char));
|
|
temp = calloc(PATH_MAX, sizeof(char));
|
|
|
|
WhosDoingWhat(DOWNLOAD, NULL);
|
|
|
|
Enter(1);
|
|
/* Please enter filename: */
|
|
pout(YELLOW, BLACK, (char *) Language(245));
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
GetstrC(File, 80);
|
|
|
|
if (( strcmp(File, "")) == 0) {
|
|
Enter(2);
|
|
/* No filename entered, Aborting. */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(246));
|
|
Enter(2);
|
|
Pause();
|
|
free(File);
|
|
free(temp);
|
|
return FALSE;
|
|
}
|
|
|
|
if (*(File) == '/' || *(File) == ' ') {
|
|
Enter(2);
|
|
/* Illegal Filename! */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(247));
|
|
Enter(2);
|
|
Pause();
|
|
free(File);
|
|
free(temp);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Get path for users home directory
|
|
*/
|
|
snprintf(temp, PATH_MAX, "%s/%s/wrk/%s", CFG.bbs_usersdir, exitinfo.Name, File);
|
|
|
|
if (stat(temp, &statfile) != 0) {
|
|
Enter(2);
|
|
/* File does not exist, please try again ...*/
|
|
pout(LIGHTRED, BLACK, (char *) Language(296));
|
|
Enter(2);
|
|
Pause();
|
|
free(File);
|
|
free(temp);
|
|
return FALSE;
|
|
}
|
|
|
|
rc = DownloadDirect(temp, TRUE);
|
|
|
|
free(File);
|
|
free(temp);
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Function will upload to users home directory
|
|
*/
|
|
int Upload_Home()
|
|
{
|
|
char *temp, *arc;
|
|
int rc = 0, Count = 0;
|
|
up_list *up = NULL, *tmpf;
|
|
|
|
WhosDoingWhat(UPLOAD, NULL);
|
|
|
|
temp = calloc(PATH_MAX, sizeof(char));
|
|
|
|
clear();
|
|
Enter(2);
|
|
|
|
rc = upload(&up);
|
|
|
|
if (rc) {
|
|
Syslog('+', "Upload home failed, rc=%d", rc);
|
|
Home();
|
|
return 1;
|
|
}
|
|
|
|
Syslog('b', "Start checking uploaded files");
|
|
Enter(2);
|
|
pout(CFG.UnderlineColourF, CFG.UnderlineColourB, (char *)"Checking your upload(s)");
|
|
Enter(2);
|
|
|
|
for (tmpf = up; tmpf; tmpf = tmpf->next) {
|
|
snprintf(temp, PATH_MAX, "%s/%s/upl", CFG.bbs_usersdir, exitinfo.Name);
|
|
chdir(temp);
|
|
|
|
Syslog('b', "Checking upload %s", tmpf->filename);
|
|
if ((arc = GetFileType(tmpf->filename)) == NULL) {
|
|
/*
|
|
* If the filetype is unknown, it is probably
|
|
* a textfile or so. Import it direct.
|
|
*/
|
|
Syslog('b', "Unknown file type");
|
|
ImportHome(basename(tmpf->filename));
|
|
Count++;
|
|
} else {
|
|
/*
|
|
* We figured out the type of the uploaded file.
|
|
*/
|
|
Syslog('b', "File type is %s", arc);
|
|
|
|
/*
|
|
* MS-DOS executables are handled direct.
|
|
*/
|
|
if ((strcmp("EXE", arc) == 0) || (strcmp("COM", arc) == 0)) {
|
|
if (!ScanDirect(basename(tmpf->filename))) {
|
|
ImportHome(basename(tmpf->filename));
|
|
Count++;
|
|
}
|
|
} else {
|
|
switch(ScanArchive(basename(tmpf->filename), arc)) {
|
|
case 0: ImportHome(basename(tmpf->filename));
|
|
Count++;
|
|
break;
|
|
case 1: break;
|
|
case 2: break;
|
|
case 3: /*
|
|
* No valid unarchiver found, just import
|
|
*/
|
|
ImportHome(basename(tmpf->filename));
|
|
Count++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Home();
|
|
|
|
ReadExitinfo();
|
|
exitinfo.Uploads += Count;
|
|
mib_uploads += Count;
|
|
WriteExitinfo();
|
|
|
|
tidy_upload(&up);
|
|
Pause();
|
|
free(temp);
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Select filearea, called from menu.
|
|
*/
|
|
void FileArea_List(char *Option)
|
|
{
|
|
FILE *pAreas;
|
|
int iAreaCount = 6, Recno = 1, iOldArea, iAreaNum = 0;
|
|
int iGotArea = FALSE; /* Flag to check if user typed in area */
|
|
int offset;
|
|
char *temp;
|
|
|
|
/*
|
|
* Save old area, incase he picks a invalid area
|
|
*/
|
|
iOldArea = iAreaNumber;
|
|
if ((pAreas = OpenFareas(FALSE)) == NULL)
|
|
return;
|
|
|
|
/*
|
|
* Count howmany records there are
|
|
*/
|
|
fseek(pAreas, 0, SEEK_END);
|
|
iAreaNum = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize;
|
|
|
|
/*
|
|
* If there are menu options, select area direct.
|
|
*/
|
|
if (strlen(Option) != 0) {
|
|
|
|
if (strcmp(Option, "F+") == 0) {
|
|
while (TRUE) {
|
|
iAreaNumber++;
|
|
if (iAreaNumber > iAreaNum)
|
|
iAreaNumber = 1;
|
|
|
|
offset = areahdr.hdrsize + ((iAreaNumber - 1) * areahdr.recsize);
|
|
if (fseek(pAreas, offset, 0) != 0) {
|
|
printf("Can't move pointer here");
|
|
}
|
|
|
|
fread(&area, areahdr.recsize, 1, pAreas);
|
|
if ((Access(exitinfo.Security, area.LTSec)) && (area.Available) && (strlen(area.Password) == 0))
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (strcmp(Option, "F-") == 0) {
|
|
while (TRUE) {
|
|
iAreaNumber--;
|
|
if (iAreaNumber < 1)
|
|
iAreaNumber = iAreaNum;
|
|
|
|
offset = areahdr.hdrsize + ((iAreaNumber - 1) * areahdr.recsize);
|
|
if (fseek(pAreas, offset, 0) != 0) {
|
|
printf("Can't move pointer here");
|
|
}
|
|
|
|
fread(&area, areahdr.recsize, 1, pAreas);
|
|
if ((Access(exitinfo.Security, area.LTSec)) && (area.Available) && (strlen(area.Password) == 0))
|
|
break;
|
|
}
|
|
}
|
|
|
|
SetFileArea(iAreaNumber);
|
|
Syslog('+', "File area %lu %s", iAreaNumber, sAreaDesc);
|
|
fclose(pAreas);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Interactive mode
|
|
*/
|
|
clear();
|
|
Enter(1);
|
|
/* File Areas */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(298));
|
|
Enter(2);
|
|
temp = calloc(81, sizeof(char));
|
|
|
|
fseek(pAreas, areahdr.hdrsize, 0);
|
|
|
|
while (fread(&area, areahdr.recsize, 1, pAreas) == 1) {
|
|
|
|
if ((Access(exitinfo.Security, area.LTSec)) && (area.Available)) {
|
|
area.Name[31] = '\0';
|
|
snprintf(temp, 81, "%5d", Recno);
|
|
pout(WHITE, BLACK, temp);
|
|
snprintf(temp, 81, " %c ", 46);
|
|
pout(LIGHTBLUE, BLACK, temp);
|
|
snprintf(temp, 81, "%-31s", area.Name);
|
|
pout(CYAN, BLACK, temp);
|
|
iAreaCount++;
|
|
|
|
if ((iAreaCount % 2) == 0) {
|
|
Enter(1);
|
|
} else {
|
|
PUTCHAR(' ');
|
|
}
|
|
}
|
|
|
|
Recno++;
|
|
|
|
if ((iAreaCount / 2) == rows) {
|
|
/* More (Y/n/=/Area #): */
|
|
pout(CFG.MoreF, CFG.MoreB, (char *) Language(207));
|
|
/*
|
|
* Ask user for Area or enter to continue
|
|
*/
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
GetstrC(temp, 7);
|
|
|
|
if (toupper(*(temp)) == Keystroke(207, 1))
|
|
break;
|
|
|
|
if ((strcmp(temp, "")) != 0) {
|
|
iGotArea = TRUE;
|
|
break;
|
|
}
|
|
|
|
iAreaCount = 2;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If user type in area above during area listing
|
|
* don't ask for it again
|
|
*/
|
|
if (!iGotArea) {
|
|
Enter(1);
|
|
/* Select Area: */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(232));
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
GetstrC(temp, 80);
|
|
}
|
|
|
|
/*
|
|
* Check if user pressed ENTER
|
|
*/
|
|
if ((strcmp(temp, "")) == 0) {
|
|
fclose(pAreas);
|
|
return;
|
|
}
|
|
|
|
iAreaNumber = atoi(temp);
|
|
|
|
/*
|
|
* Do a check in case user enters a negative value
|
|
*/
|
|
if (iAreaNumber < 1)
|
|
iAreaNumber = 1;
|
|
|
|
offset = areahdr.hdrsize + ((iAreaNumber - 1) * areahdr.recsize);
|
|
if (fseek(pAreas, offset, 0) != 0)
|
|
printf("Can't move pointer there.");
|
|
else
|
|
fread(&area, areahdr.recsize, 1, pAreas);
|
|
|
|
/*
|
|
* Do a check if area is greater or less number than allowed,
|
|
* security access level, is oke, and the area is active.
|
|
*/
|
|
if (iAreaNumber > iAreaNum || iAreaNumber < 1 ||
|
|
(Access(exitinfo.Security, area.LTSec) == FALSE) ||
|
|
(strlen(area.Name) == 0)) {
|
|
Enter(1);
|
|
/* Invalid area specified - Please try again ...*/
|
|
pout(LIGHTRED, BLACK, (char *) Language(233));
|
|
Enter(2);
|
|
Pause();
|
|
fclose(pAreas);
|
|
iAreaNumber = iOldArea;
|
|
SetFileArea(iAreaNumber);
|
|
free(temp);
|
|
return;
|
|
}
|
|
|
|
SetFileArea(iAreaNumber);
|
|
Syslog('+', "File area %lu %s", iAreaNumber, sAreaDesc);
|
|
|
|
/*
|
|
* Check if file area has a password, if it does ask user for it
|
|
*/
|
|
if ((strlen(area.Password)) > 2) {
|
|
Enter(2);
|
|
/* Please enter Area Password: */
|
|
pout(WHITE, BLACK, (char *) Language(299));
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
GetstrC(temp, 20);
|
|
Enter(1);
|
|
|
|
if ((strcmp(temp, area.Password)) != 0) {
|
|
/* Password is incorrect */
|
|
pout(LIGHTRED, BLACK, (char *) Language(234));
|
|
Syslog('!', "Incorrect File Area # %d password given: %s", iAreaNumber, temp);
|
|
SetFileArea(iOldArea);
|
|
} else {
|
|
/* Password is correct */
|
|
pout(WHITE, BLACK, (char *) Language(235));
|
|
}
|
|
Enter(2);
|
|
Pause();
|
|
}
|
|
|
|
free(temp);
|
|
fclose(pAreas);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Show filelist from current area, called from the menu.
|
|
*/
|
|
void Copy_Home()
|
|
{
|
|
char *File, *temp1, *temp2;
|
|
int err, Found = FALSE;
|
|
struct _fdbarea *fdb_area = NULL;
|
|
|
|
File = calloc(81, sizeof(char));
|
|
temp1 = calloc(PATH_MAX, sizeof(char));
|
|
temp2 = calloc(PATH_MAX, sizeof(char));
|
|
|
|
Enter(1);
|
|
/* Please enter filename: */
|
|
pout(YELLOW, BLACK, (char *) Language(245));
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
GetstrC(File, 80);
|
|
Enter(2);
|
|
|
|
if ((strcmp(File, "")) == 0) {
|
|
/* No filename entered, Aborting. */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(246));
|
|
Enter(2);
|
|
Pause();
|
|
free(File);
|
|
free(temp1);
|
|
free(temp2);
|
|
return;
|
|
}
|
|
|
|
if (*(File) == '/' || *(File) == ' ') {
|
|
/* Illegal Filename! */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(247));
|
|
Enter(2);
|
|
Pause();
|
|
free(File);
|
|
free(temp1);
|
|
free(temp2);
|
|
return;
|
|
}
|
|
|
|
if (Access(exitinfo.Security, area.DLSec) == FALSE) {
|
|
pout(YELLOW, BLACK, (char *) Language(236));
|
|
Enter(2);
|
|
Pause();
|
|
free(File);
|
|
free(temp1);
|
|
free(temp2);
|
|
return;
|
|
}
|
|
|
|
if ((fdb_area = mbsedb_OpenFDB(iAreaNumber, 30)) == NULL) {
|
|
free(File);
|
|
free(temp1);
|
|
free(temp2);
|
|
return;
|
|
}
|
|
|
|
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
|
|
if ((strcasecmp(File, fdb.Name) == 0) || (strcasecmp(File, fdb.LName) == 0)) {
|
|
|
|
Found = TRUE;
|
|
if (((fdb.Size + Quota()) > (CFG.iQuota * 1048576))) {
|
|
/* You have not enough diskspace free to copy this file */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(279));
|
|
Enter(1);
|
|
Syslog('+', "Copy homedir, not enough quota");
|
|
} else {
|
|
snprintf(temp1, PATH_MAX, "%s/%s", area.Path, fdb.LName); /* Use real longname here */
|
|
snprintf(temp2, PATH_MAX, "%s/%s/wrk/%s", CFG.bbs_usersdir, exitinfo.Name, File);
|
|
colour(CFG.TextColourF, CFG.TextColourB);
|
|
/* Start copy: */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(289));
|
|
PUTSTR(File);
|
|
PUTCHAR(' ');
|
|
|
|
Syslog('b', "Copy from : %s", temp1);
|
|
Syslog('b', "Copy to : %s", temp2);
|
|
|
|
if ((err = file_cp(temp1, temp2))) {
|
|
/* Failed! */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(353));
|
|
WriteError("Copy %s to homedir failed, code %d", File, err);
|
|
} else {
|
|
/* Ok */
|
|
PUTSTR((char *) Language(200));
|
|
Syslog('+', "Copied %s from area %d to homedir", File, iAreaNumber);
|
|
}
|
|
Enter(1);
|
|
}
|
|
}
|
|
}
|
|
mbsedb_CloseFDB(fdb_area);
|
|
|
|
if (!Found) {
|
|
/* File does not exist, please try again ... */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(296));
|
|
Enter(1);
|
|
}
|
|
|
|
Pause();
|
|
free(File);
|
|
free(temp1);
|
|
free(temp2);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Edit the list of tagged files.
|
|
*/
|
|
void EditTaglist()
|
|
{
|
|
FILE *tf;
|
|
int i, x, Fg, Count;
|
|
char *temp;
|
|
|
|
if ((tf = fopen("taglist", "r+")) == NULL) {
|
|
Enter(1);
|
|
/* No files tagged. */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(361));
|
|
Enter(2);
|
|
Pause();
|
|
return;
|
|
}
|
|
|
|
temp = calloc(81, sizeof(char));
|
|
if (utf8)
|
|
chartran_init((char *)"CP437", (char *)"UTF-8", 'B');
|
|
|
|
while (TRUE) {
|
|
clear();
|
|
fseek(tf, 0, SEEK_SET);
|
|
Count = 0;
|
|
/* # Area Active Size Cost File */
|
|
/* 123 12345 123456 12345678 12345 */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(355));
|
|
Enter(1);
|
|
colour(LIGHTGREEN, BLACK);
|
|
PUTSTR(chartran(fLine_str(79)));
|
|
|
|
while ((fread(&Tag, sizeof(Tag), 1, tf) == 1)) {
|
|
Count++;
|
|
|
|
if (Tag.Active)
|
|
Fg = WHITE;
|
|
else
|
|
Fg = LIGHTGRAY;
|
|
|
|
snprintf(temp, 81, "%3d ", Count);
|
|
pout(Fg, BLACK, temp);
|
|
|
|
Fg--;
|
|
snprintf(temp, 81, "%5d ", Tag.Area);
|
|
pout(Fg, BLACK, temp);
|
|
|
|
Fg--;
|
|
if (Tag.Active)
|
|
/* Yes */
|
|
snprintf(temp, 81, "%-6s ", (char *) Language(356));
|
|
else
|
|
/* No */
|
|
snprintf(temp, 81, "%-6s ", (char *) Language(357));
|
|
pout(Fg, BLACK, temp);
|
|
|
|
Fg--;
|
|
snprintf(temp, 81, "%8d ", (int)(Tag.Size));
|
|
pout(Fg, BLACK, temp);
|
|
|
|
Fg--;
|
|
snprintf(temp, 81, "%5d ", Tag.Cost);
|
|
pout(Fg, BLACK, temp);
|
|
|
|
Fg--;
|
|
snprintf(temp, 81, "%s", Tag.LFile);
|
|
pout(Fg, BLACK, temp);
|
|
|
|
Enter(1);
|
|
}
|
|
colour(LIGHTGREEN, BLACK);
|
|
PUTSTR(chartran(fLine_str(79)));
|
|
|
|
/* (T)oggle active, (E)rase all, (ENTER) to continue: */
|
|
pout(WHITE, RED, (char *) Language(358));
|
|
|
|
i = toupper(Readkey());
|
|
colour(CFG.CRColourF, CFG.CRColourB);
|
|
|
|
if (i == Keystroke(358, 0)) {
|
|
Enter(2);
|
|
/* Enter file number, 1.. */
|
|
snprintf(temp, 81, "%s%d ", (char *) Language(359), Count);
|
|
PUTSTR(temp);
|
|
|
|
GetstrC(temp, 5);
|
|
x = atoi(temp);
|
|
|
|
if ((x > 0) && (x <= Count)) {
|
|
if (fseek(tf, (x - 1) * sizeof(Tag), SEEK_SET) == 0) {
|
|
if (fread(&Tag, sizeof(Tag), 1, tf) == 1) {
|
|
if (Tag.Active)
|
|
Tag.Active = FALSE;
|
|
else
|
|
Tag.Active = TRUE;
|
|
|
|
fseek(tf,(x - 1) * sizeof(Tag), SEEK_SET);
|
|
fwrite(&Tag, sizeof(Tag), 1, tf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
chartran_close();
|
|
|
|
if (i == Keystroke(358, 1)) {
|
|
fclose(tf);
|
|
unlink("taglist");
|
|
free(temp);
|
|
return;
|
|
}
|
|
|
|
if ((i == '\r') || (i == '\n')) {
|
|
fclose(tf);
|
|
free(temp);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* View a file in the current area, menu 103.
|
|
* If a file name is given, display direct,
|
|
* else ask for filename to view.
|
|
*/
|
|
void ViewFile(char *name)
|
|
{
|
|
char *File, *temp, *arc;
|
|
int count, total, rc, found = FALSE;
|
|
FILE *fp;
|
|
struct _fdbarea *fdb_area = NULL;
|
|
|
|
Syslog('+', "ViewFile(%s)", printable(name, 0));
|
|
|
|
if (Access(exitinfo.Security, area.LTSec) == FALSE) {
|
|
Enter(1);
|
|
/* You don't have enough security to list this area */
|
|
pout(YELLOW, BLACK, (char *) Language(236));
|
|
Enter(2);
|
|
Pause();
|
|
return;
|
|
}
|
|
|
|
File = calloc(PATH_MAX, sizeof(char));
|
|
|
|
if ((name != NULL) && strlen(name)) {
|
|
strcpy(File, name);
|
|
} else {
|
|
Enter(2);
|
|
/* Please enter filename: */
|
|
pout(YELLOW, BLACK, (char *) Language(245));
|
|
colour(CFG.InputColourF, CFG.InputColourB);
|
|
GetstrC(File, 80);
|
|
|
|
if ((strcmp(File, "")) == 0) {
|
|
free(File);
|
|
return;
|
|
}
|
|
|
|
if (*(File) == '.' || *(File) == '*' || *(File) == ' ' || *(File) == '/') {
|
|
Enter(1);
|
|
/* Illegal Filename! */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(247));
|
|
Enter(2);
|
|
Pause();
|
|
free(File);
|
|
return;
|
|
}
|
|
|
|
Strlen = strlen(File);
|
|
Strlen--;
|
|
|
|
if (*(File + Strlen) == '.' || *(File + Strlen) == '/' || *(File + Strlen) == ' ') {
|
|
Enter(1);
|
|
/* Illegal Filename! */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(247));
|
|
Enter(2);
|
|
Pause();
|
|
free(File);
|
|
return;
|
|
}
|
|
|
|
if ((!strcmp(File, "files.bbs")) || (!strcmp(File, "00index")) || (strstr(File, (char *)".html"))) {
|
|
Enter(1);
|
|
/* Illegal Filename! */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(247));
|
|
Enter(2);
|
|
Pause();
|
|
free(File);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Now check if this file is present
|
|
*/
|
|
if ((fdb_area = mbsedb_OpenFDB(iAreaNumber, 30)) == NULL) {
|
|
free(File);
|
|
return;
|
|
}
|
|
|
|
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
|
|
if (((strcasecmp(File, fdb.Name) == 0) || (strcasecmp(File, fdb.LName) == 0)) && (!fdb.Deleted)) {
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
mbsedb_CloseFDB(fdb_area);
|
|
|
|
if (!found) {
|
|
Enter(1);
|
|
/* File does not exist, please try again ... */
|
|
pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(296));
|
|
Enter(2);
|
|
free(File);
|
|
Pause();
|
|
return;
|
|
}
|
|
|
|
snprintf(File, PATH_MAX, "%s/%s", sAreaPath, fdb.LName);
|
|
arc = GetFileType(File);
|
|
Syslog('+', "File to view: %s, type %s", fdb.LName, printable(arc, 0));
|
|
|
|
if (arc != NULL) {
|
|
found = FALSE;
|
|
temp = calloc(PATH_MAX, sizeof(char));
|
|
snprintf(temp, PATH_MAX, "%s/etc/archiver.data", getenv("MBSE_ROOT"));
|
|
|
|
if ((fp = fopen(temp, "r")) != NULL) {
|
|
fread(&archiverhdr, sizeof(archiverhdr), 1, fp);
|
|
while (fread(&archiver, archiverhdr.recsize, 1, fp) == 1) {
|
|
if ((strcmp(arc, archiver.name) == 0) && (archiver.available)) {
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
fclose(fp);
|
|
}
|
|
|
|
if (!found || (strlen(archiver.varc) == 0)) {
|
|
Syslog('+', "No archiver view for %s available", File);
|
|
Enter(1);
|
|
/* Archiver not available */
|
|
pout(CFG.HiliteF, CFG.HiliteB, Language(442));
|
|
Enter(2);
|
|
free(File);
|
|
free(temp);
|
|
Pause();
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Archiver viewer is available. Make a temp file which we will
|
|
* display to the user.
|
|
*/
|
|
snprintf(temp, PATH_MAX, "%s/%s/temptxt", CFG.bbs_usersdir, exitinfo.Name);
|
|
rc = execute_str(archiver.varc, File, NULL, (char *)"/dev/null", temp, (char *)"/dev/null");
|
|
Syslog('+', "Display temp file %s", temp);
|
|
DisplayTextFile(temp);
|
|
unlink(temp);
|
|
free(temp);
|
|
} else {
|
|
/*
|
|
* Most likely a textfile, first check.
|
|
*/
|
|
total = count = 0;
|
|
if ((fp = fopen(File, "r"))) {
|
|
while (TRUE) {
|
|
rc = fgetc(fp);
|
|
if (rc == EOF)
|
|
break;
|
|
total++;
|
|
if (isascii(rc))
|
|
count++;
|
|
}
|
|
fclose(fp);
|
|
}
|
|
if (((count * 10) / total) < 8) {
|
|
Syslog('+', "This is not a ASCII textfile");
|
|
Enter(1);
|
|
pout(CFG.HiliteF, CFG.HiliteB, Language(17));
|
|
Enter(2);
|
|
Pause();
|
|
free(File);
|
|
return;
|
|
}
|
|
Syslog('+', "Display text file %s", File);
|
|
DisplayTextFile(File);
|
|
}
|
|
|
|
free(File);
|
|
}
|
|
|
|
|