file.cpp 9.64 KB
Newer Older
1
2
3
/* Synchronet file transfer-related functions */

/* $Id$ */
4
// vi: tabstop=4
5
6
7
8
9

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
10
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 *																			*
 * This program 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			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "sbbs.h"

/****************************************************************************/
/* Prints all information of file in file_t structure 'f'					*/
/****************************************************************************/
void sbbs_t::fileinfo(file_t* f)
{
44
	char	ext[513];
45
	char 	tmp[512];
46
	char	tmp2[64];
47
	char	path[MAX_PATH+1];
48
	char	fname[MAX_PATH+1];
49
	char*	real_fname;
50
	uint	i,j;
51

52
	current_file = f;
53
54
55
56
57
58
	for(i=0;i<usrlibs;i++)
		if(usrlib[i]==cfg.dir[f->dir]->lib)
			break;
	for(j=0;j<usrdirs[i];j++)
		if(usrdir[i][j]==f->dir)
			break;
59

60
	getfilepath(&cfg,f,path);
61
62
	real_fname = getfname(path);
	unpadfname(f->name, fname);
63
64
	bprintf(text[FiLib],i+1,cfg.lib[cfg.dir[f->dir]->lib]->lname);
	bprintf(text[FiDir],j+1,cfg.dir[f->dir]->lname);
65
66
67
	bprintf(text[FiFilename],fname);
	if(strcmp(real_fname, fname) && strcmp(f->desc, real_fname))	/* Different "actual" filename */
		bprintf(text[FiFilename], real_fname);
68

69
	if(f->size!=-1L)
70
71
		bprintf(text[FiFileSize],ultoac(f->size,tmp)
			, byte_estimate_to_str(f->size, tmp2, sizeof(tmp2), /* units: */1024, /* precision: */1));
72
73
74
75
76
	bprintf(text[FiCredits]
		,(cfg.dir[f->dir]->misc&DIR_FREE || !f->cdt) ? "FREE" : ultoac(f->cdt,tmp));
	bprintf(text[FiDescription],f->desc);
	bprintf(text[FiUploadedBy],f->misc&FM_ANON ? text[UNKNOWN_USER] : f->uler);
	if(f->date)
77
78
79
		bprintf(text[FiFileDate],timestr(f->date));
	bprintf(text[FiDateUled],timestr(f->dateuled));
	bprintf(text[FiDateDled],f->datedled ? timestr(f->datedled) : "Never");
80
	bprintf(text[FiTimesDled],f->timesdled);
81
	if(f->size>0 && f->timetodl>0)
82
83
84
85
		bprintf(text[FiTransferTime],sectostr(f->timetodl,tmp));
	if(f->altpath) {
		if(f->altpath<=cfg.altpaths) {
			if(SYSOP)
86
87
				bprintf(text[FiAlternatePath],cfg.altpath[f->altpath-1]); 
		}
88
		else
89
90
			bprintf(text[InvalidAlternatePathN],f->altpath); 
	}
91
	bputs(text[FileHdrDescSeparator]);
92
	if(f->misc&FM_EXTDESC) {
93
		getextdesc(&cfg,f->dir,f->datoffset,ext);
94
		putmsg(ext,P_NOATCODES);
95
96
		CRLF; 
	}
97
	if(f->size==-1L) {
98
		bprintf(text[FileIsNotOnline],f->name);
99
		if(SYSOP)
100
			bprintf("%s\r\n",path);
101
	}
102
103
	if(f->opencount)
		bprintf(text[FileIsOpen],f->opencount,f->opencount>1 ? "s" : nulstr);
104
	current_file = NULL;
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
}


/****************************************************************************/
/* Increments the opencount on the file data 'f' and adds the transaction 	*/
/* to the backout.dab														*/
/****************************************************************************/
void sbbs_t::openfile(file_t* f)
{
	char str1[256],str2[4],str3[4],ch;
	int file;

	/************************************/
	/* Increment open count in dat file */
	/************************************/
120
	sprintf(str1,"%s%s.dat",cfg.dir[f->dir]->data_dir,cfg.dir[f->dir]->code);
121
122
	if((file=nopen(str1,O_RDWR))==-1) {
		errormsg(WHERE,ERR_OPEN,str1,O_RDWR);
123
124
		return; 
	}
125
126
127
128
	lseek(file,f->datoffset+F_OPENCOUNT,SEEK_SET);
	if(read(file,str2,3)!=3) {
		close(file);
		errormsg(WHERE,ERR_READ,str1,3);
129
130
		return; 
	}
131
	str2[3]=0;
132
	ultoa(atoi(str2)+1,str3,10);
133
134
135
136
137
	putrec(str2,0,3,str3);
	lseek(file,f->datoffset+F_OPENCOUNT,SEEK_SET);
	if(write(file,str2,3)!=3) {
		close(file);
		errormsg(WHERE,ERR_WRITE,str1,3);
138
139
		return; 
	}
140
141
142
143
	close(file);
	/**********************************/
	/* Add transaction to BACKOUT.DAB */
	/**********************************/
144
	sprintf(str1,"%sbackout.dab",cfg.node_dir);
145
146
	if((file=nopen(str1,O_WRONLY|O_APPEND|O_CREAT))==-1) {
		errormsg(WHERE,ERR_OPEN,str1,O_WRONLY|O_APPEND|O_CREAT);
147
148
		return; 
	}
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
	ch=BO_OPENFILE;
	write(file,&ch,1);				/* backout type */
	write(file,cfg.dir[f->dir]->code,8); /* directory code */
	write(file,&f->datoffset,4);		/* offset into .dat file */
	write(file,&ch,BO_LEN-(1+8+4)); /* pad it */
	close(file);
}

/****************************************************************************/
/* Decrements the opencount on the file data 'f' and removes the backout  	*/
/* from the backout.dab														*/
/****************************************************************************/
void sbbs_t::closefile(file_t* f)
{
	char	str1[256],str2[4],str3[4],ch,*buf;
	int		file;
	long	length,l,offset;

	/************************************/
	/* Decrement open count in dat file */
	/************************************/
170
	sprintf(str1,"%s%s.dat",cfg.dir[f->dir]->data_dir,cfg.dir[f->dir]->code);
171
172
	if((file=nopen(str1,O_RDWR))==-1) {
		errormsg(WHERE,ERR_OPEN,str1,O_RDWR);
173
174
		return; 
	}
175
176
177
178
	lseek(file,f->datoffset+F_OPENCOUNT,SEEK_SET);
	if(read(file,str2,3)!=3) {
		close(file);
		errormsg(WHERE,ERR_READ,str1,3);
179
180
		return; 
	}
181
182
183
	str2[3]=0;
	ch=atoi(str2);
	if(ch) ch--;
184
	ultoa(ch,str3,10);
185
186
187
188
189
	putrec(str2,0,3,str3);
	lseek(file,f->datoffset+F_OPENCOUNT,SEEK_SET);
	if(write(file,str2,3)!=3) {
		close(file);
		errormsg(WHERE,ERR_WRITE,str1,3);
190
191
		return; 
	}
192
193
194
195
	close(file);
	/*****************************************/
	/* Removing transaction from BACKOUT.DAB */
	/*****************************************/
196
	sprintf(str1,"%sbackout.dab",cfg.node_dir);
197
198
199
200
	if(flength(str1)<1L)	/* file is not there or empty */
		return;
	if((file=nopen(str1,O_RDONLY))==-1) {
		errormsg(WHERE,ERR_OPEN,str1,O_RDONLY);
201
202
		return; 
	}
203
	length=(long)filelength(file);
deuce's avatar
deuce committed
204
	if((buf=(char *)malloc(length))==NULL) {
205
206
		close(file);
		errormsg(WHERE,ERR_ALLOC,str1,length);
207
208
		return; 
	}
209
210
	if(read(file,buf,length)!=length) {
		close(file);
deuce's avatar
deuce committed
211
		free(buf);
212
		errormsg(WHERE,ERR_READ,str1,length);
213
214
		return; 
	}
215
216
	close(file);
	if((file=nopen(str1,O_WRONLY|O_TRUNC))==-1) {
217
		free(buf);
218
		errormsg(WHERE,ERR_OPEN,str1,O_WRONLY|O_TRUNC);
219
220
		return; 
	}
221
222
223
224
225
226
227
228
	ch=0;								/* 'ch' is a 'file already removed' flag */
	for(l=0;l<length;l+=BO_LEN) {       /* in case file is in backout.dab > 1 */
		if(!ch && buf[l]==BO_OPENFILE) {
			memcpy(str1,buf+l+1,8);
			str1[8]=0;
			memcpy(&offset,buf+l+9,4);
			if(!stricmp(str1,cfg.dir[f->dir]->code) && offset==f->datoffset) {
				ch=1;
229
230
231
232
233
				continue; 
			}
		}
		write(file,buf+l,BO_LEN); 
	}
deuce's avatar
deuce committed
234
	free(buf);
235
236
237
238
239
240
241
242
243
244
245
	close(file);
}

/****************************************************************************/
/* Prompts user for file specification. <CR> is *.* and .* is assumed.      */
/* Returns padded file specification.                                       */
/* Returns NULL if input was aborted.                                       */
/****************************************************************************/
char * sbbs_t::getfilespec(char *str)
{
	bputs(text[FileSpecStarDotStar]);
246
	if(!getstr(str,64,K_NONE))
247
		strcpy(str,ALLFILES);
248
#if 0
249
250
	else if(!strchr(str,'.') && strlen(str)<=8)
		strcat(str,".*");
251
#endif
252
253
254
255
256
257
258
259
	if(sys_status&SS_ABORT)
		return(0);
	return(str);
}

/****************************************************************************/
/* Checks to see if filename matches filespec. Returns 1 if yes, 0 if no    */
/****************************************************************************/
260
extern "C" BOOL filematch(const char *filename, const char *filespec)
261
262
263
264
265
266
267
{
    char c;

	for(c=0;c<8;c++) /* Handle Name */
		if(filespec[c]=='*') break;
		else if(filespec[c]=='?') continue;
		else if(toupper(filename[c])!=toupper(filespec[c])) return(FALSE);
268
269
	if(filespec[8]==' ')	/* no extension specified */
		return(TRUE);
270
271
272
273
274
275
276
277
278
279
280
281
282
283
	for(c=9;c<12;c++)
		if(filespec[c]=='*') break;
		else if(filespec[c]=='?') continue;
		else if(toupper(filename[c])!=toupper(filespec[c])) return(FALSE);
	return(TRUE);
}

/*****************************************************************************/
/* Checks the filename 'fname' for invalid symbol or character sequences     */
/*****************************************************************************/
bool sbbs_t::checkfname(char *fname)
{
    int		c=0,d;

284
285
	if(fname[0]=='-'
		|| strcspn(fname,ILLEGAL_FILENAME_CHARS)!=strlen(fname)) {
286
		lprintf(LOG_WARNING,"Suspicious filename attempt: '%s'",fname);
deuce's avatar
deuce committed
287
		hacklog((char *)"Filename", fname);
288
289
		return(false); 
	}
290
291
	if(strstr(fname,".."))
		return(false);
292
#if 0	/* long file name support */
293
294
	if(strcspn(fname,".")>8)
		return(false);
295
#endif
296
297
	d=strlen(fname);
	while(c<d) {
298
		if(fname[c]<=' ' || fname[c]&0x80)
299
			return(false);
300
301
		c++; 
	}
302
303
	return(true);
}