home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / CLIPPER / DHIDE / DBFHIDE.PRG
Text File  |  1992-11-17  |  10KB  |  305 lines

  1.  
  2. // -------- DBFHIDE.PRG  --------------------------------- //
  3. //                                                           
  4. // AUTHOR : Rick Hellewell                                   
  5. // DATE   : November 17, 1992  2:17 pm
  6. // NOTICE : Copyright (c) 1991 - 1992 by Rick Hellewell
  7. //             All Rights Reserved                           
  8. // VERSION: Clipper 5.01                                     
  9. // PURPOSE: Hides the DBF file from casual prying eyes       
  10. // Notes  : Reverses the first 128 bytes of the dbf file
  11. //            during file access
  12. //          Placed in public domain by author (CIS:  70724,3300)
  13. // Program Version : 1.10                                       
  14. // ------------------------------------------------------- //
  15.  
  16.  
  17.    /* 
  18.    SYNTAX: DBFHIDE([dbf file name], [lfileopen])
  19.  
  20.       parameters:
  21.          dbfname     (C)    name of the database to access
  22.          fileopen    (L)    .f. if closing the file, so reverse the header 
  23.                             .t. if opening the file, so un-reverse the header
  24.  
  25.       returns:
  26.          .t.   if no errors
  27.          .f.   if errors during file accesses
  28.  
  29.    Program samples:
  30.  
  31.       Open a database for use
  32.          dbfname = "TEST.DBF"
  33.          IF DBFHIDE(dbfname, .t.) 
  34.             ? "File is available"
  35.          ELSE
  36.             ? "File access error"
  37.          ENDIF
  38.  
  39.       Close a database after use:
  40.          dbfname = "TEST.DBF"
  41.          IF DBFHIDE(dbfname, .f.)
  42.             ? "File is hidden from use"
  43.          ELSE
  44.             ? "File access error"
  45.          ENDIF
  46.    
  47.       Can also be run from the DOS prompt (if compiled as a standalone)
  48.          DBFHIDE TEST.DBF .T.
  49.  
  50.  
  51.    PROGRAM DESCRIPTION AND NOTES
  52.  
  53.    Performs limited DBF file security by reversing the first 128 
  54.    bytes of the DBF file.  When the file is closed, the first 128 
  55.    bytes of a DBF file are written "backwards".  (You can change this
  56.    value if you want to by specifying a different number for the 
  57.    READSIZE, READBUFF, and SWAPCOUNT variables set at the beginning
  58.    of the routine.)
  59.  
  60.    When the file is opened, the first 128 bytes of a DBF file are
  61.    modified by writing those bytes "backwards", which makes the 
  62.    DBF file readable by Clipper/xBase.  (Since that area of the DBF 
  63.    header is reversed when the file is closed.)
  64.  
  65.    NOTE: When using this routine, the VERY FIRST ACCESS to a normal DBF
  66.    file must be called with LFILEOPEN set to .f. to encrypt the header.  Then
  67.    all futures accesses of the database must be done through this routine.
  68.    You can do this with a batch file that contains the command
  69.       FOR %%1 in (*.DBF) DO DBFHIDE %%1 .F.
  70.  
  71.    Since the DBF file header has been "damaged" when the file is closed
  72.    using this routine, access to the data through xBase will be difficult,
  73.    but not impossible.  This routine DOES NOT encrypt the data, so someone
  74.    could peek at it. And if you were patient, you could use a program 
  75.    such as Norton's FILEFIX to fix the DBF file's header.
  76.  
  77.    To help identify whether a file has been "hidden", a three character
  78.    code is written to the end of the file (variable "hidecode", set at the 
  79.    beginning of the function).  The hidecode is checked only when it is 
  80.    time to encode the header -- it is added at the end of the file,
  81.    overwriting the last three bytes necessary (this eliminates extra
  82.    hidecodes at the end of the file).  If the hidecode is not at the end 
  83.    of an opened file, such as when you append records, it is placed there
  84.    when the file is secured.
  85.  
  86.    An "unhidden" file -- available for normal data access -- has the
  87.    NORMCODE text written at the end of the file.  This text may be
  88.    overwritten when data is added to the DBF, so it is not checked
  89.    when it comes time to hide the file.
  90.  
  91.    REPLACING SOME FUNCTIONS WITH YOUR OWN
  92.  
  93.    The DBF files are opened by a DBFOPEN() function.  The DBF files are 
  94.    closed by a DBFCLOSE() function.  Replace these functions or calls
  95.    with your own routines to open/close files and indexes if desired.
  96.  
  97.    This routine uses FOPEN(), FREAD(), and FCLOSE() file functions with 
  98.    limited error checking.  Replace with your own routines if desired.
  99.  
  100.    ALERT() functions are used for screen messages.  Replace with your
  101.    own routines if desired.
  102.  
  103.    USING IT ELSEWHERE
  104.  
  105.    A similar process could be used to "encrypt" index or other files.
  106.    You'll need to make the appropriate changes to recognize non-DBF 
  107.    files.
  108.  
  109.    AN OBVIOUS BUT UNCOMMON POSSIBILITY
  110.  
  111.    Note that if the DBF file is really small, there program will die, 
  112.    since the program assumes that the file has at least 128 bytes. 
  113.    However, since most databases are larger than that, it shouldn't be
  114.    a problem in most cases.
  115.  
  116.    NO GUARANTEES HERE
  117.  
  118.    This function seems to work OK.  There is probably some error checking 
  119.    that should be added to make it more bulletproof.  And you may find
  120.    some "amatuerish" ways to do things, but I'm still learning.
  121.  
  122.    Your comments would be appreciated...
  123.  
  124.    Rick Hellewell, CIS 70724,3300
  125.  
  126.    */
  127.  
  128.  
  129. function DBFHIDE ( dbfname, lfileopen)
  130.  
  131. #include "fileio.ch"
  132.  
  133. // some variables used here
  134. private fileopen := .t.
  135. private hidecode := "RGH"         // code written to end of hidden file
  136. private normcode := "OK!"         // code written at end of normal file
  137.  
  138. // make sure there is at least one parameter passed
  139. if pcount() < 1
  140.    alert("No database specified!;Process cancelled.")
  141.    return .f.
  142. endif
  143.  
  144. // make sure that the file has a .dbf extension
  145. if at(".", dbfname) = 0
  146.    dbfname = alltrim(dbfname)+".DBF"
  147. endif
  148.  
  149. // make sure the file exists
  150. if ! file(dbfname)
  151.    alert("Can't find the " + dbfname + " database;Process cancelled.")
  152.    return .f.
  153. endif
  154.  
  155. if pcount() < 2
  156.    alert("Syntax error!;DBFHIDE([dbf file name], [lfileopen]")
  157.    return .f.
  158. endif
  159.  
  160. // convert the fileopen variable if run from DOS command line
  161. if valtype(lfileopen) = "C"
  162.    do case
  163.       case upper(lfileopen) == ".T."
  164.          fileopen = .t.
  165.    
  166.       case upper(lfileopen) == ".F."
  167.          fileopen = .f.
  168.  
  169.       otherwise
  170.          fileopen = .t.
  171.  
  172.    end case
  173. endif
  174.  
  175. if fileopen = .t.        // opening the file
  176.    if ! swaphead(dbfname)
  177.       alert("Problem reversing data (177)")
  178.       return .f.
  179.    endif
  180.    if ! dbfopen(dbfname)
  181.       alert("Problem opening the database (181)")
  182.       return .f.
  183.    endif
  184. else                    // closing the file
  185.    if ! dbfclose(dbfname)
  186.       alert("Problem closing the database (186)")
  187.       return .f.
  188.    endif
  189.    if ! swaphead(dbfname)
  190.       alert("Problem reversing data (190)")
  191.       return .f.
  192.    endif
  193.  
  194. endif   
  195.  
  196. // all ok!, return to caller
  197. return .t.
  198.  
  199. // ---------------------------------------------------------------- //
  200. static function swaphead(dbfname)
  201.    // reverse the first 128 bytes of the file
  202.    // put/remove the key from the end of the file
  203.    
  204.    // change "128" to your desired size
  205.    local readsize := 128, readbuff := space(128), swapcount := 128
  206.    local temp := ""                     // temp text holder
  207.  
  208.    dbfhandle  = fopen(dbfname, 2)       // open binary file for read/write
  209.    if ferror() != 0
  210.       alert("Can't open the database in binary mode (210)")
  211.       return .f.
  212.    endif
  213.  
  214.    // need to decode
  215.    // read the first 128 bytes
  216.    if fread(dbfhandle, @readbuff, readsize) <> readsize
  217.       alert("Error reading database in binary mode (217)")
  218.       return .f.
  219.    endif
  220.  
  221.    // got the 128 bytes, reverse it
  222.    for i = swapcount to 1 step -1
  223.       temp += substr(readbuff, i,1)
  224.    next i
  225.    if len(temp) != swapcount
  226.       alert("Error: temporary variable <> " + alltrim(str(swapcount)) + ";"+str(len(temp)) + " (226)" )
  227.       return .f.
  228.    endif
  229.    
  230.    // write the reversed data back to the file
  231.    fseek(dbfhandle, 0)
  232.    if fwrite(dbfhandle, temp, readsize) != readsize
  233.       alert("Error writing database in binary mode (233)")
  234.       return .f.
  235.    endif
  236.    
  237.    // write the ending code if fileopen = .t.
  238.    if fileopen = .t.                      // open database flag
  239.       if endwrite(normcode) = .f.         // write normal ending code
  240.          fclose(dbfhandle)                // error, close it
  241.          return .f.                       // and return .f.
  242.       endif
  243.    else                                   // close database flag
  244.       if endwrite(hidecode) = .f.         // write ending code
  245.          fclose(dbfhandle)                // error, close it
  246.          return .f.                       // and return .f.
  247.       endif
  248.    endif
  249.  
  250.    // all writes OK, so close the file
  251.    fclose(dbfhandle)
  252. return .t.
  253.  
  254. // ---------------------------------------------------------------- //
  255. static function endwrite(endtext)
  256.  
  257.    // write the endtext at the end of the file
  258.    local tempbuff := space(3), tempsize := 3, endsize := len(endtext)
  259.  
  260.    fseek(dbfhandle,-3,2)             // get to last three bytes
  261.    if fread(dbfhandle, @tempbuff, tempsize) != tempsize
  262.       alert("Error reading database in binary mode (262)")
  263.       return .f.
  264.    endif
  265.    if tempbuff == endtext          
  266.       // the endtext is already there, so don't add another one
  267.    else                             // need to put the endtext there
  268.       fseek(dbfhandle,-3,2)
  269.       if fwrite(dbfhandle, @endtext, endsize) != endsize
  270.          alert("Error writing database in binary mode (270)")
  271.          return .f.
  272.       endif
  273.    endif
  274.  
  275. return .t.
  276.  
  277. // ---------------------------------------------------------------- //
  278. static function dbfopen(dbfname)
  279.    // open the database using standard USE commands
  280.    // can be replaced with your open file functions
  281.  
  282. if select(dbfname) > 0
  283.    select(dbfname)
  284.    return .t.
  285. else
  286.    use (dbfname) new
  287.    return .t.
  288. endif
  289.  
  290. return NIL                 // bogus return 
  291.  
  292. // ---------------------------------------------------------------- //
  293. static function dbfclose(dbfname)
  294.    // close the database using standard USE commands
  295.    // can be replaced with your close file functions
  296.  
  297. close(dbfname)
  298. return .t.
  299.  
  300. // ---------------------------------------------------------------- //
  301.  
  302. // ------------------------ end of file --------------------------- //
  303.  
  304.  
  305.