home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
CLIPPER
/
DHIDE
/
DBFHIDE.PRG
Wrap
Text File
|
1992-11-17
|
10KB
|
305 lines
// -------- DBFHIDE.PRG --------------------------------- //
//
// AUTHOR : Rick Hellewell
// DATE : November 17, 1992 2:17 pm
// NOTICE : Copyright (c) 1991 - 1992 by Rick Hellewell
// All Rights Reserved
// VERSION: Clipper 5.01
// PURPOSE: Hides the DBF file from casual prying eyes
// Notes : Reverses the first 128 bytes of the dbf file
// during file access
// Placed in public domain by author (CIS: 70724,3300)
// Program Version : 1.10
// ------------------------------------------------------- //
/*
SYNTAX: DBFHIDE([dbf file name], [lfileopen])
parameters:
dbfname (C) name of the database to access
fileopen (L) .f. if closing the file, so reverse the header
.t. if opening the file, so un-reverse the header
returns:
.t. if no errors
.f. if errors during file accesses
Program samples:
Open a database for use
dbfname = "TEST.DBF"
IF DBFHIDE(dbfname, .t.)
? "File is available"
ELSE
? "File access error"
ENDIF
Close a database after use:
dbfname = "TEST.DBF"
IF DBFHIDE(dbfname, .f.)
? "File is hidden from use"
ELSE
? "File access error"
ENDIF
Can also be run from the DOS prompt (if compiled as a standalone)
DBFHIDE TEST.DBF .T.
PROGRAM DESCRIPTION AND NOTES
Performs limited DBF file security by reversing the first 128
bytes of the DBF file. When the file is closed, the first 128
bytes of a DBF file are written "backwards". (You can change this
value if you want to by specifying a different number for the
READSIZE, READBUFF, and SWAPCOUNT variables set at the beginning
of the routine.)
When the file is opened, the first 128 bytes of a DBF file are
modified by writing those bytes "backwards", which makes the
DBF file readable by Clipper/xBase. (Since that area of the DBF
header is reversed when the file is closed.)
NOTE: When using this routine, the VERY FIRST ACCESS to a normal DBF
file must be called with LFILEOPEN set to .f. to encrypt the header. Then
all futures accesses of the database must be done through this routine.
You can do this with a batch file that contains the command
FOR %%1 in (*.DBF) DO DBFHIDE %%1 .F.
Since the DBF file header has been "damaged" when the file is closed
using this routine, access to the data through xBase will be difficult,
but not impossible. This routine DOES NOT encrypt the data, so someone
could peek at it. And if you were patient, you could use a program
such as Norton's FILEFIX to fix the DBF file's header.
To help identify whether a file has been "hidden", a three character
code is written to the end of the file (variable "hidecode", set at the
beginning of the function). The hidecode is checked only when it is
time to encode the header -- it is added at the end of the file,
overwriting the last three bytes necessary (this eliminates extra
hidecodes at the end of the file). If the hidecode is not at the end
of an opened file, such as when you append records, it is placed there
when the file is secured.
An "unhidden" file -- available for normal data access -- has the
NORMCODE text written at the end of the file. This text may be
overwritten when data is added to the DBF, so it is not checked
when it comes time to hide the file.
REPLACING SOME FUNCTIONS WITH YOUR OWN
The DBF files are opened by a DBFOPEN() function. The DBF files are
closed by a DBFCLOSE() function. Replace these functions or calls
with your own routines to open/close files and indexes if desired.
This routine uses FOPEN(), FREAD(), and FCLOSE() file functions with
limited error checking. Replace with your own routines if desired.
ALERT() functions are used for screen messages. Replace with your
own routines if desired.
USING IT ELSEWHERE
A similar process could be used to "encrypt" index or other files.
You'll need to make the appropriate changes to recognize non-DBF
files.
AN OBVIOUS BUT UNCOMMON POSSIBILITY
Note that if the DBF file is really small, there program will die,
since the program assumes that the file has at least 128 bytes.
However, since most databases are larger than that, it shouldn't be
a problem in most cases.
NO GUARANTEES HERE
This function seems to work OK. There is probably some error checking
that should be added to make it more bulletproof. And you may find
some "amatuerish" ways to do things, but I'm still learning.
Your comments would be appreciated...
Rick Hellewell, CIS 70724,3300
*/
function DBFHIDE ( dbfname, lfileopen)
#include "fileio.ch"
// some variables used here
private fileopen := .t.
private hidecode := "RGH" // code written to end of hidden file
private normcode := "OK!" // code written at end of normal file
// make sure there is at least one parameter passed
if pcount() < 1
alert("No database specified!;Process cancelled.")
return .f.
endif
// make sure that the file has a .dbf extension
if at(".", dbfname) = 0
dbfname = alltrim(dbfname)+".DBF"
endif
// make sure the file exists
if ! file(dbfname)
alert("Can't find the " + dbfname + " database;Process cancelled.")
return .f.
endif
if pcount() < 2
alert("Syntax error!;DBFHIDE([dbf file name], [lfileopen]")
return .f.
endif
// convert the fileopen variable if run from DOS command line
if valtype(lfileopen) = "C"
do case
case upper(lfileopen) == ".T."
fileopen = .t.
case upper(lfileopen) == ".F."
fileopen = .f.
otherwise
fileopen = .t.
end case
endif
if fileopen = .t. // opening the file
if ! swaphead(dbfname)
alert("Problem reversing data (177)")
return .f.
endif
if ! dbfopen(dbfname)
alert("Problem opening the database (181)")
return .f.
endif
else // closing the file
if ! dbfclose(dbfname)
alert("Problem closing the database (186)")
return .f.
endif
if ! swaphead(dbfname)
alert("Problem reversing data (190)")
return .f.
endif
endif
// all ok!, return to caller
return .t.
// ---------------------------------------------------------------- //
static function swaphead(dbfname)
// reverse the first 128 bytes of the file
// put/remove the key from the end of the file
// change "128" to your desired size
local readsize := 128, readbuff := space(128), swapcount := 128
local temp := "" // temp text holder
dbfhandle = fopen(dbfname, 2) // open binary file for read/write
if ferror() != 0
alert("Can't open the database in binary mode (210)")
return .f.
endif
// need to decode
// read the first 128 bytes
if fread(dbfhandle, @readbuff, readsize) <> readsize
alert("Error reading database in binary mode (217)")
return .f.
endif
// got the 128 bytes, reverse it
for i = swapcount to 1 step -1
temp += substr(readbuff, i,1)
next i
if len(temp) != swapcount
alert("Error: temporary variable <> " + alltrim(str(swapcount)) + ";"+str(len(temp)) + " (226)" )
return .f.
endif
// write the reversed data back to the file
fseek(dbfhandle, 0)
if fwrite(dbfhandle, temp, readsize) != readsize
alert("Error writing database in binary mode (233)")
return .f.
endif
// write the ending code if fileopen = .t.
if fileopen = .t. // open database flag
if endwrite(normcode) = .f. // write normal ending code
fclose(dbfhandle) // error, close it
return .f. // and return .f.
endif
else // close database flag
if endwrite(hidecode) = .f. // write ending code
fclose(dbfhandle) // error, close it
return .f. // and return .f.
endif
endif
// all writes OK, so close the file
fclose(dbfhandle)
return .t.
// ---------------------------------------------------------------- //
static function endwrite(endtext)
// write the endtext at the end of the file
local tempbuff := space(3), tempsize := 3, endsize := len(endtext)
fseek(dbfhandle,-3,2) // get to last three bytes
if fread(dbfhandle, @tempbuff, tempsize) != tempsize
alert("Error reading database in binary mode (262)")
return .f.
endif
if tempbuff == endtext
// the endtext is already there, so don't add another one
else // need to put the endtext there
fseek(dbfhandle,-3,2)
if fwrite(dbfhandle, @endtext, endsize) != endsize
alert("Error writing database in binary mode (270)")
return .f.
endif
endif
return .t.
// ---------------------------------------------------------------- //
static function dbfopen(dbfname)
// open the database using standard USE commands
// can be replaced with your open file functions
if select(dbfname) > 0
select(dbfname)
return .t.
else
use (dbfname) new
return .t.
endif
return NIL // bogus return
// ---------------------------------------------------------------- //
static function dbfclose(dbfname)
// close the database using standard USE commands
// can be replaced with your close file functions
close(dbfname)
return .t.
// ---------------------------------------------------------------- //
// ------------------------ end of file --------------------------- //