#====================<[ Version 1.7 November 24, 2015 ]>====================
 1. Fixed code in SQLiteningServer.BAS : ProcessRequest() and the %reqConnect handler. 
    Was not adding the required data (for bytes 7-?).
 2. Added new slKill function that allows a connection to be killed via program code.
 3. Updated the slExeBind documentation to correct the "CN" flag in slBuildBindDat to "CE".
 4. Updated code to correct error handling in slSetNamedLocks.
 5. Fix for issue with slDisconnect causing lock ups (added Reset thMutex in SQLiteDisconnect).


#====================<[ Version 1.6.5 December 6, 2012 ]>====================
 1. Added the two new functions (slIsDatabaseNameValid and slIsTableNameValid) to 
    the Special and Universial API's

 2. Fixed bug when passing a database handle across threads in remote mode.  

 3. Fixed bug in slExeBind that would sometimes store invalid integer or real numbers.

 4. Fixed all array scan commands so they would not execute when the array is not dimensioned.

 5. Fixed the return version routines in SQLiteningClient and SQLiteningServer. They would 
    fail only if you are  doing multi connects within threads. 



#====================<[ Version 1.6 July 22, 2012 ]>====================
 1. Fixed bug in slBuildInsertOrUpdate where a value of only . or - or + 
    was incorrectly considered to be numeric.

 2. Changed SQLiteningServer to show the server version number in 
    the Log whenever the service is started.

 3. Changed SQLiteningServer to include more CriticalSections when doing
    read/write of flat files.

 4. The ImHere thread in SQLiteningClient was not being stopped correctly 
    causing memory errors.

 5. The TCP socket was not being properly closed in SQLiteningClient causing 
    memory leaks.
     
 6. Fixed bug in SQLiteningServer that was not deleting the files in the Temp
    folder if the database was closed using slClose.

 7. Fixed bug in SQLiteningServer that was creating unneeded files in the Temp
    folder for smaller select statements.

 8. Added a MutEx synchronizing event in SQLiteningClient to prevent the ImHere 
    message to be sent while sending/receiving a real message.

 9. Fixed bug in SQLiteningClient that was not handling the timer going pas
    midnight in the ImHere routine

10. Fixed bug in SQLiteningServer that was using Word instead of Dword to store 
    the timer value.

11. Added version info to the Dll's and Exe so you are able to determine the version
    by viewing the properties.

12. Added slGetStatus(5) which returns the elapsed seconds since last message sent 
    to server. Will always return an empty string if running in local mode.

13. Changed SQLitening to close all open sets in slDisconnect.

14. Changed SQLitening to correctly report a TCP timeout as error -18.

15. Added the F ModChar to the slSel commands.  This can be used to change the size 
    of the first Row Data Chunk (RDC) which normally defaults to half the size of 
    MaxChunkSize which is set in the Config file.

16. Fixed the tool in QLiteningServerAdmin to kill an active connection. It was
    not working properly.

17. Added a new tool to SQLiteningServerAdmin which will display the version 
    numbers of the currently running SQLiteningServer and SQLite.

18. Added a seventh flag to the slGetStatus -- 3 = Return SQLitening flag settings.
              7 = One if a SQLite library is loaded.
                      (Local = SQLite3.DLL, Remote = SQLiteningClient.DLL)

19. Added a :LogNote: file name to slPutFile. The FileData is written to the remote 
    log as a Note entry.  The Note entry is also new.

20. Improved slGetTableColumnNames to allow for qualifying the table name with
    a database name.  Previously would only work with tables in the Main database.

21. Added the slIsDatabaseNameValid function which will returns %True if DatabaseName 
    is valid(opened or attached).

22. Added the slIsTableNameValid function which returns %True if TableName is 
    valid(exist, has been created).

23. Added the new MaxConnections entry to the SQLiteningServerCfg file. Controls the number 
    of concurrent connections.

24. Added slGetStatus(6) which returns the SQLitening and SQLite version numbers.

25. Added two new SQLitening Error Codes.  
      -22 - The max concurrent connections (set in Cfg file) was exceeded.
      -23 - SQLitening.Dll, SQLiteningClient.Dll, and SQLiteningServer.Exe
            must all be the same file version number.  Note that this error 
            was returned as -8 in earlier versions

 26. Update SQLite3.Dll to the version 3.7.13 dated June 11, 2012.

 27. Added several re-declares to SQLitening.Inc to allow you to use 
     WString data types in PB. You must uncomment them to use.  You can 
     also re-name them to anything you like.

#====================<[ Version 1.5 July 4, 2011 ]>====================
 1. ADDED -- command/function called slGetDatabaseAndFileNames which will
    return a list of database and file names that are currently opened and
    attached.  The name entries are returned as a delimited text string which 
    is $NUL separated.  Each entry contains two elements, a database name and 
    a file name.  The two elements are separated by the vertical bar (|) 
    character.  The first entry is always the Main database from the slOpen 
    command.  The second entry will be the Temp database, but only if there 
    are temporary tables currently created.  The rest of the entries, if any, 
    will be the attached databases.  There are no file names assigned to 
    temporary tables nor temporary databases.  

 2. ADDED -- command/function called slGetFieldDataTypes which will return
    the data type for each of the columns in all the selected rows returned 
    by the passed select Statement. The date types of each field for each row 
    are returned as comma delimited strings.  Each row will return a stirng 
    of numeric values, one value for each column. Will return an empty string 
    if an error occurs or no row is selected.  The SQLite data types are: 
            1=Integer, 2=Float, 3=Text, 4=Blob, 5=Null.
   If, for example, your select statment returned 3 rows each with 4 columns
   the returning string might be:  3314,3552,3315

 3. ADDED -- the slSelBind function. This new command allows you to use binary 
    data(Blobs and Unicode) in where clauses and it's use will also prevent SQL 
    injection.

 4. IMPROVED -- the optional Where parameter in slBuildInsertOrUpdate
    as follows: If the Where value is omitted or is an empty string ("") 
    then will build an Insert statement else will build an Update statement. 
    When building an Update statement and the Where value is not "*" then a 
    Where clause will be appended as " Where " and then the Where value. If 
    the Where value is "*" then the Update statement will not have a Where 
    clause (Caution: All records in table will be updated!).

 5. IMPROVED -- When a client process ends it normally notifies the server 
    and the connection is closed.  For unknown reasons this does not happen 
    sometimes, resulting in a Half-Open connection.  To assure this is 
    trapped, SQLiteningClient was changed to insure a message is sent at 
    least every two minutes. If no real message has been sent then a "ImHere" 
    message will be sent.  Also changed SQLiteningServer to close a connection 
    if no message has been received for three minutes.  This type of 
    close will be logged as "WentAway".

 6. CHANGED -- the name of ZLib.Dll to SQLiteningZLib.Dll to avoid conflicts 
    with other application that also use ZLib, but a different one.  There 
    are two freely available, ZLib1.Dll and ZLibWApi.Dll which are normally 
    renamed to just ZLib.Dll.  ZLibWApi.Dll has all the functions of ZLib.Dll 
    plus the ability to create and read .Zip files.  ZLibWApi.Dll uses standard 
    calling conventions while ZLib1.Dll uses the C calling convention therefore 
    they are not interchangable.  ZLibWApi.Dll, renamed to SQLiteningZLib.Dll, 
    is the one used with SQLiteing.  The prior ZLib.Dll distributed by SQLitening 
    should be deleted from your running folders.

 7. FIXED -- SQLiteningServerAdmin to ensure that the SQLiteningServer.Cfg 
    file exists before attempting to run a tool.

 8. FIXED -- bug in SQLitening.  The slGetTables would not retrun the table 
    names for the Temp database.

 9. FIXED -- bug in SQLiteningServer.  All databases were automatically closed 
    when a connection ends.  For speed reasons, no check was made to determine 
    if a database was still open.  If a database was explicit closed with slClose 
    and the server was under stress (hi use) then an error could occur when 
    it was closed the second time.  Changed to check if a database is still 
    open before closing when connection ends.  

 10.FIXED -- slGetStatus request 1 to properly return the time the lock was set.   

 11.FIXED -- the 'f' ModChar in slOpen as follows:      
      f  = Do not enable foreign key support.  
              If 'f' is passed then will send: PRAGMA foreign_keys=Off
              If 'f' is not passed then will send: PRAGMA foreign_keys=On

 12.FIXED --  bug in SQLiteningServer. It would sometimes show the connetion
    timed out when it actually was dropped.

 13.FIXED --  bug in slSelStr. It would not allow you to use chr$(0) as either 
    of the delimiters.

 14.REMOVED -- slsGetInsertID but only from the Special API, it will remain 
    in the other APIs.  It was not returning the correct values in VB.
    Any of the APIs can use the "Select last_insert_rowid()" which is a 
    core SQLite function.

 15.DISALLOWED -- slPushSet and slPopSet in Remote mode.  If it was used in 
    Remote mode the results were erroneous.

 18. Update SQLite3.Dll to the version 3.7.7.1 dated June 29, 2011.

#===================<[ Version 1.4  July 12, 2010 ]>===================
 1. SQLitening.Dll is now thread-safe.  You can now have multiple threads
    accessing your SQLite database in both local and remote mode.  This
    will allow you to have multiple connections per client to the server, 
    one for each thread.  This can greatly increase response time for 
    situations where you can take advantage of multiple threads.  A new
    example program (ExampleD.Bas) is included using multiple theads.
    This new feature also allows database Procs to use SQLitening.Dll 
    rather than have to call SQlite direct (makes coding Procs much easier).  
    There is a new Proc (SQLiteningProcB.Bas) included using this new feature.

 2. Added slCopyDatebase.  This new function will allow you to make copies/backups 
    of a database.  Normally you make copies/backups by locking the database and then
    copying the database by using an external tool like FileCopy.  This method works well
    but has the following shortcomings: 
      -- Any database clients wishing to write to the database file while a backup is 
         being created must wait until the shared lock is relinquished. 
      -- It cannot be used to copy data to or from :memory: nor Temp databases. 
      -- If a power failure or operating system failure occurs while copying the resulting
         copied database may be corrupt. 
    The slCopyDatabase function uses the new SQLite OnlineBackup API which was created 
    to address these shortcomings. slCopyDatabase allows the contents of one database to be 
    copied into another database, overwriting the original contents of the target database. 
    The copy operation may be done incrementally, in which case the source database does not 
    need to be locked for the duration of the copy, only for the brief periods of time when 
    it is actually being read from. This allows other database users to continue uninterrupted 
    while the copy is made.  See http://www.sqlite.org/backup.html for more info about the 
    OnlineBackup API.

 3. Added slSelStr.  This new function returns selected rows as a delimited text string.  
    Each field and record is delimited by a single character.  The default field delimiter
    is $BS while the default record delimiter is $VT.  These defaults can be changed. This 
    is easier to use than slSelAry and can be very handy for small amounts of returning data. 
    Is excellent for testing the occurrence of a condition and processing Pragma returns.
    Lets say you wanted to know if there were any rows that had an
    'X' in column F1 of table T1:
          if len(slSelStr(Select 1 from T1 where F1='X' Limit 1) then
               ' if the above is true then you have at least 1 with 'X'
          end if
    This will display the page size -- ? slSelStr("Pragma page_size")

 4. Updated Example C to include examples of the new slCopyDatabase and slSelStr.  
    Added a new Example D to demo multi-threading.

 5. Enhanced slExeBind to be able to Insert or Update multiple records.  In 
    prior releases slExeBind was only needed to work with blobs or text values 
    that contained nulls.  Now it can be used to greatly improve Insert or 
    Update speed.  My tests show it can improve them by as much as 45%.  Check 
    out ExampleB.Bas for a sample that will Insert 50,000 records two 
    different ways in either local or remote mode.  One way is to use 
    slExeBind while the other slower way is to us slExe and stack the SQL 
    insert statements.  Also note in this example the use of an array and the 
    Join$ command to greatly improve concatenation speed.  

 6. Added ModChars i,I,D,Z to slBuildBindDat which will allow for the 
    building of dats to bind Integer, Integer64, Double, and Null values.  

 7. Added the ability in slGetFile to pass a get position and a get length.
    Using a position and length is useful when you only want to get a 
    portion of the file.  This also may be needed for very large files 
    even when you want to get the whole file.

 8. Added the ability in slPutFile to pass a put position. Using a 
    position is useful when you only want to put a portion of the file.  
    This also may be needed for very large files even when you want to 
    put the whole file.  Removed the create file in remote mode 
    restriction.  Added D and T ModChars which allow you to delete a
    file and control when the file is truncated.

 9. Changed slSel so that when no set is passed (defaults to zero) or 
    the passed set number is zero it will first close that set. This 
    will prevent error -14 (%SQLitening_InvalidSetNumber).

10. Changed slOpen to automatically enable SQLite foreign key support. 
    SQLite disables this feature by default (for backwards compatibility), 
    so must be enabled separately for each database connection. Also 
    added the f ModChar to allow you to not enable foreign key support.

11. Added the C ModChar to slSel.  This will first close the passed set 
    number.  This will prevent error -14 (%SQLitening_InvalidSetNumber) 
    but should be used with caution.

12. Changed slConnect to check that the client and server versions are
    same.  If not then %SQLitening_AccessDenied is returned.

13. Changed slConnect so that when a second connect request is made it
    will just return if the current connection is still active.  Before
    it would just return without checking if still active.

14. Added a new request to slGetStatus.  Request 4 will check if the 
    current remote connection is active and return either "Yes" or "No"
    This is like a 'ping' which will cause a trip to serve.

15. Add a quiet mode parm to SQLiteningServerAdmin so it can be run
    from a script without any user messages to answer. Pass the Q command 
    line parm proceeded with a / or - (OS standard).  The Q must be followed
    by a numerical value for the action requested as follows:
         1 = Install
         2 = Start --- will first Install if required
         3 = Install and Start
         4 = Stop
         8 = Uninstall --- will first Stop if required
        12 = Stop and Uninstall
        16 = Reload Config
    This program will return the following codes if in Quiet mode:
        0 = All OK
        1 = Can't perform request, service in wrong status
        2 = Request failed.
        9 = Service in unknown or invalid status

16. Fixed bug in slSel when running in local mode and using the "B" ModChar.

17. Added a new sample proc called SQLiteningProcsB.Bas.  This proc uses
    SQLitening for all processsing.

18. Update SQLite3.Dll to the version 3.6.23.1 dated March 30 2010.

#=================<[ Version 1.3  November 1, 2009 ]>==================
 1. Removed the call to sqlite3_thread_cleanup in SQLiteningServer.Bas. 
    It had become obsolete.
 
 2. Added calls to sqlite3_initialize at server start and sqlite3_shutdown
    at server stop in SQLiteningServer.Bas.  These are new SQLite functions.
 
 3. Added call to sqlite3_shutdown in SQLitening.Bas when process detaches.
 
 4. Change SQLitening.Dll so all sets are automatically closed when slClose
    is called.
 
 5. Change SQLiteningServer.Exe to timeout a connection after a number of
    minutes of no activity.  The default number is 30.  You can change it
    in the config file.  You can do an empty string slExe if you need to 
    keep a connection active.  Error %SQLitening_SendOrReceiveError will 
    occur if you attempt to use a connection that has timed out.
 
 6. Added the SystemTemp database to SQLiteningServer.Exe to be able to store 
    stuff like the named locks and connection data.
 
 7. Fixed a bug in SQLiteningServer.Exe that was sending back the wrong 
    return value if the slSel was huge.
 
 8  Changed the error handling on the following ruts to be consistent with other 
    ruts that returned string.
             slGetColumnName
             slGetTableColumnNames
             slGetTableNames

 9. Added rut slSetRelNamedLocks which will set or release named lock(s).  
    This can be used to implement application locks or to simulate record 
    locks.  Names are locked on a server-wide basis.  If a name has been 
    locked by one client, the server blocks any request by another client for 
    a lock with the same name.  This allows clients that agree on a given lock 
    name to use the name to perform cooperative advisory locking.  But be 
    aware that it also allows a client that is not among the set of 
    cooperating clients to lock a name and thus prevent any of the cooperating 
    clients from locking that name.  One way to reduce the likelihood of this 
    is to use lock names that are database-specific or application-specific.  
    Named locks are only used in remote mode.  They are ignored when running 
    in local mode.  Will also optionally do a Sel command but only if the lock 
    request was successful. 

10. Added the following ModChars to slSel, slSelAry, and to the SelStatemnt of
    slSetRelNameLocks:
      Bn = Do a Begin Transaction before doing the Sel command. The type
           of Begin is controlled by the value of n as follows:
              0 = Deferred. This is the default if n is omitted.
              1 = Immediate.
              2 = Exclusive.
           This allows for database locking and selecting in one trip to the server.
      R =  Release all named locks owned by this connection.
      
11. Added the following ModChars to slExe:
      R =  Release all named locks owned by this connection.
 
12. Added rut slGetStatus which returns the requested status which is normally 
    a delimited list of returning data.  The following requests are currently 
    valid:
         1 = Return all named locks. 
         2 = Return all connections.
         3 = Return SQLitening flag settings.

13. Added the server name suffix to SQLiteningServerAdmin.Bas messages and 
    changed the log to also show the suffix. Having a unique suffix allows 
    multiple services (servers) to be running on same computer.

14. Added a new dialog to SQLiteningServerAdmin which allows for the following tools:
            Refresh the Config Flags and FACT
            List all Active Connectons
            Kill one Active Connection
    You already had the ability to "Refresh" but the other two are new.

15. Added two new items to the config file.
      MaxChunkSize = Number K  ---  Controls the size of Row Data Chunks which are returned from Select statements
                                    The value is in K so the actual size is * 1000.  Default is 500.

      ConnectionTimeOut = Number Minutes --- Control the number of minutes the server will wait to receive a message
                                             from an active connection.  Default is 30.
                                             

#====================<[ Version 1.2 June 19 200 ]>=====================
1. Changed SQLitening.Dll to close the database when detaching
   and running local. This will process and remove any pending 
   journal file. This does not change the end result it just 
   cleans up the journal file sooner.  

2. Fixed Load/Unload problem with RunProc.

3. Added the slIsOpen function which will return %True if a 
   database is open.

4. Added slPushSet and slPopSet.  Push will save the data about 
   an open set while pop will restore the data.  This allows you
   to reuse a set number with out first closing it.

5. Added a global flag (AreConnected) to improve the control of running
   remote or local and allowing for retrying to connect to server if 
   first attempt(s) failed.

6. Fixed bug in server that would cause a crash if Close was called 
   at wrong time.

7. Added bind blob and bind text examples to SQLiteningProcA.Bas.

8. Added another conditional compile Server Exit #4 which will fire 
   for ever slOpen.  This is the place to create SQLite custom function.

9. Added Exit #4 to SQLiteningServerExits.Bas and included as example
   of two SQLite customer functions (MyF0 and MyF2).

10.Added the "S" ModChar the both slGetFile and slPutFile.
      S  = Open file with Shared lock, default is both Read and Write locks.
           This only applies to standard files, not Ini.

11.There will now be three supported API's. Basic, Special, and Universal.
   See doc in SQLitening.Txt.  Support for SQLiteningVB is discontinued.
    
12.Included the zip file UserMods.Zip which contains user contributed 
   additions and/or modifications to SQLitening soruce code.

13.Update SQLite3.Dll to version 3.6.15 dated 06-15-2009.


==================<[ Version 1.11 January 28, 200 ]>==================
1. Changed slGetInsertID to prevent random GPF's.
   My testing says that PB9 will handle Quads returning from C but only if 
   you use early binding (no call Dword).  SQLitening.Dll must use late 
   binding cause it will dynamically call either SQLite3.Dll or 
   SQLiteningClient.Dll therefore PB9 doesn't help here.  SQLiteningServer, 
   on the other hand, does use early binding so PB9 can do it's thing there.  
   Local mode will no longer call the SQLite API to obtain the last inserted 
   ID instead it will get it using the last_insert_rowid() function.  This is 
   a little slower than the API call but should eliminate the GPF problem.  
   Remote mode will continue calling the API but have removed the assembler 
   stuff and will let PB9 do it's Quad thing.  

2. Changed a failed connect to remain in remote mode so all following
   commands will also fail.  It was returning to neutural mode so following
   commands would process in local mode --- not good.

3. Added a new optional parameter to the slConnect command called wsOutData.
   OutData, if parm is passed and if return is zero, will contain the 
   following values delimited by the $BS character.  There is only one 
   value being returned now but others may be added in future so use the 
   parse$ command.
      1 = The unique TcpFileNumber assigned by the server to this connection.  This 
          can be used whenever a unique number for a connection is needed.  This
          same value is passed to ceratin exits.
   IMPORTANT!!!  All programs using slConnect should be recompiled when using
                 this release.

4. Added another parm to be passed to a user coded proc.  This new parm
   (byval rlTcpFileNumber as Long) will contain the unique number assigned 
   by the server to a connection.
   IMPORTANT!!!  All user procs should be recompiled when using this release.

5. Changed the starting of SQLiteningServerMonitor to be a conditional compile.
   If SQLiteningServer is compiled with %CompileStartServerMonitor = %True then 
   SQLiteningServerMonitor will be started when SQLiteningServer is started.
   %CompileStartServerMonitor = %False is the default.

6. Added the concept of 'Exits' to SQLiteningServer.  The term 'Exit' comes 
   from the main program (SQLiteningServer.Exe) 'Exiting' to a sub program 
   (SQLiteningServerExits.Dll) which contains your custom code and then 
   waiting for the return code.  If the return is zero then the server will 
   continue to process else will return that error value to the calling 
   application program or the main program may end with an error.  Exits are 
   placed at strategic points in the process loop of SQLiteningServer.  More 
   exits may be added in future.  The sub program must be thread safe, it can 
   access SQLite3.Dll directly or it can use SQLitening.Dll which is thread safe.  
   See the sample source SQLiteningServerExits.Bas for what exits are available 
   and what parameters are passed and other information.  There currently are 5 exits 
   available and are controlled by the following conditional compile equates: 
      %CompileExit_1_Connect, %CompileExit_2_Disconnect, %CompileExit_3_Access
      %CompileExit_101_Start, %CompileExit_102_Stop
   The default is that they are all %False. Because the exits are activated only
   if you want them, there is no overhead for the ones who don't use them.

7. Added the 'Q' and 'c' ModChars to slSelAry. The 'Q' will return a one dimension
   array with delimited column values.  The 'c' will not return the column names
   in entry zero.
      Q# = Return a one dimension array where each column is delimited by a
           single character.  That character is determined by the ascii value
           at #. The default is to return a two dimension array.
      c = Do not return the column names as a row of data at index zero.  The
          default is to return the column names as row zero.

8. Change SQLitening.Dll so all sets are automatically closed when the Dll is detached. 

9. Update SQLite3.Dll to version 3.6.7.


===================<[ Version 1.1 November 6 2008 ]>===================
1.  Removed the "P" ModChar from slFX, slFNX, and slSelAry.
    Just use "D" and "U" ModChars to Decrypt and Uncompress. 
    Purpose: The "P" ModChar was redundant and bloated the code.

2.  Deleted the slGetFieldType routine and replaced it with 
    slIsFieldNull.  The slGetFieldType could not be handled
    the same way in both local and remote mode.  It was 
    decided that knowing the data type other than Null was
    not needed.
    Purpose: Make local and remote mode are the same.

3.  Added the slGetHandle routine.  This will return either
    the open database or open set handle.
    Purpose: To be able to call SQLite directly. Only allowed 
             in local mode. 

4.  Added the %ReturnAllErrors conditional compile equate.
    Purpose: So SQLitening.Dll can be compiled with Return 
             Errors as the default.

5.  Added the slConvertDat function which accepts a string and 
    returns a converted string. The posible conversion are:
         Compress, Encrypt, Uncompress, Decrypt, Hexadecimal
    Purpose: This returned hex string can be used in a where 
             clause for Blob data.  It can also be used to 
             insert or update Blob data (slExeBind is more 
             efficient).

6.  Added the ability to have a user coded monitor process running
    along with the server process. SQLiteningServer will now shell 
    to the SQLiteningServerMonitor.Exe process when it starts. This 
    process will run as long as the server is running, it will exit 
    when server is stopped. If this monitor process is not required 
    then just delete SQLiteningServerMonitor.Exe.
    Purpose: This is the place you can code things like writing back 
             up copies or do any other database or file maintenance 
             using all the power of SQLitening in local mode.  

7.  Added the ability to have user coded procs within a Dll called
    SQLiteningProcs.Dll. These procs will allow you to write your 
    own code which will run at the server accessing SQLite in local
    mode.  Your can call a proc using slRunProc or the SQLite function
    load_extension (no parms allowed using load_extension). These procs 
    talk to SQLite directly without going thru SQLitening. Not using 
    SQLitening is required cause SQLitening.Dll is not thread safe and 
    the server starts a new thread for each connection.  These procs 
    will also work fine in local mode. This concept is similar to database 
    procedures in Oracle and MySQL except here you get to code in Basic 
    rather that their proprietary language.
    Purpose: Using procs can greatly improve response time by reducing
             messages to/from server.

8.  Added the ServiceNameSuffix entry to the server config file.  
    Purpose: To allow multiple services (servers) to be running on same 
             computer.  You could, for example, have both a Test and Prod
             server.

9.  Added SQLiteningVB.Dll which is a bridge DLL for Visual Basic to 
    handle the ByVal string problem.  The SQLiteningVB.Ini file has
    also changed. A VB program will call SQLiteningVB which in turn 
    will call SQLitening for the ruts that use ByVal strings. These 
    are not fully tested because I do not have VB.
    Purpose: To allow Visual Basic to use SQLitening.


=================<[ Version 1.06 October 24, 2008 ]>==================
1.  Changed version numbers scheme.  You can always tell what version
    a file is by looking and it's time.  The hour will be the major
    version number while the minute will be the minor number.

2.  Made changes to the include file so all programs must be recompiled.
    Also be sure you install all Dll's and Exe's as a set.

3.  Changed slExeBind to accept a string of BindDat entries instead of 
    a string array.  A BindDat entry is built using a new routine called
    slBuildBindDat. This will make slExeBind easer to code, run faster, 
    and easer to understand.  See new doc for slExeBindDat and check
    out slBuildBindDat.
    IMPORTANT: All programs that used slExeBind must be changed and
    recompiled.

4.  Completely recoded error processing.  If you are returning errors
    then the slGetError or a new routine called slGetErrorNumber will
    return the last error.  slGetError returns a string containing 
    "number = description" while slGetErrorNumber returns a long 
    containing only the number.  Since the last error number is stored
    in a global long, slGetErrorNumber is very fast where slGetError
    must do a call to SQLite.

5.  The "E" Modchar now has an optional 'm' modifier which is the message 
    display modifier and can be:
           0 = No message is displayed.  This is the default.
           1 = Display a warning message with OK button.  Error is
               returned when OK pressed.
           2 = Display a question message with OK and Cancel buttons.
               If they press OK, error is returned.  If they press
               Cancel, will exit process.
    So now if you do slSetProcessMods "E1" then if any error occurs
    SQLitening will display the error message and then return to your
    program.

6.  Changed SQLiteningClient.Dll to return all errors rather
    than exiting processing. Added following error number.
   -18 = Error sending or receiving message"
         ' Server went away or message length error

7.  Added "E" ModChar to slGetRow.  If an error occurs and you are
    returning errors then will return %False.  

8.  Added "D" ModChar to slSel which will allow duplicate column names.
    Not recommended if using slFN or slFNX because you will always get
    the first value returned.  SQLite does not normally return qualified 
    column names.  SQLite will return C1 twice if you Select T1.C1, T2.C1. 
    So the solution is to alias one of them with the As clause as follows
    Select T1.C1, T2.C1 as C1Again.  There is a Pragma called "full_column_names"
    which forces SQLite to return qualified names, but does not seem to 
    work if you Select *.  Read up on it and use if you like.  I like 
    using an alias because it is less code.

9.  The change to slExeBind allows for VB and VB.Net to use SQLitening
    as is.  No special shell needed.  So I added two include files. 
    SQLiteningVB.Inc and SQLiteningVBNET.Inc.  Did light testing with 
    VB5 and VB 2008 (.Net).  Seems to work fine.  slSelAry is removed 
    from the include files because array passing is not compatibly.
    slSelAry is not required -- just handy sometimes. Also the return 
    value for slGetInsertID is changed to Currency for VB.

10. SQLitening.Txt has many changes.


================<[ Version 5 -- September 10, 2008 ]>=================
1.  Fixed bug in checking for duplicate column names in Select statement.

2.  Changed slClose and slCloseSet to never raise an error.

3.  Added the "E" ModChar to the two extended get field 
    commands (slFX and slFNx).
      E = Return errors. The return value will be an empty string. The 
      error number, preceded by #, will be set back into ModChars.
    The non extended get field commands (slF and slFN) will 
    still exit process if there is an error.

4.  Added global flags to slSetProcessMods that will 
    return all errors.  The two new ModChars are:
      E  = Return all errors. SQLitening will not exit the process except
           for certain unusually situations like when it can not load a
           library.  This setting is global.
      e =  Only return errors if the "E" ModChar is passed with the command.
           This is the default.  If no "E" passed then errors will cause a
           message to display and the process to exit. This setting is global.

5.  Added following ModChars to slConnect for security reasons:
      u  = Do not pass user name.
      c  = Do not pass computer name.
      i  = Do not pass IP address.

6.  Eliminated the User entry in log.  The user data is now placed in the
    Conn entry.  That eliminated the LogUser entry in the config file.

7.  Changed when the Conn entry is logged and add user data to it.
    Added the LogInvalidInMessage entry to the config file.
      LogInvalidInMessage = Yes or No  ---   Controls the logging of invalid incoming messages.  If Yes and 
                                             the message is invalid (first is not slConnect or is a wrong 
                                             length) is received then an Eror message is logged. If omitted
                                             then will default to No.   No will prevent hackers/attackers from 
                                             filling the log.

8.  Logging of Conn/Dcon will now only occur if the first message
    is a valid slConnect.  Hackers/attackers won't fill log. 

9.  Changed slConnect so that if already connected the will just 
    return rather than establish another connection.


==================<[ Version 4 -- August 26, 2008 ]>==================

1.  Fixed documentation for slAttach, slOpen, slGetFile, and slPutFile

2.  Fixed security bug that allowed slOpen to create a file without 
    correct password.

3.  Fixed bug in slBuildInsertOrUpdate.

4.  Changed slOpen and slAttach to return error -9 (File does not 
    exist) rather than error 14 (Unable to open the database file) if 
   the file does not exist.

5.  Changed slConnect if $NUL is passed as the Server then will run
    in local mode.

6.  Add ability to force a value to be numeric in slBuildInsertOrUpdate.

7.  Fixed bug in slExe error handling.

8.  Added checking for duplicate column names in Select statement. Will
    raise error -13 if occurs.  SQLite allows duplicate column names
    in the Select statement which would cause slFN and slFNX to return
    undesirable stuff.

9.  Strengthened the documentation in SQLitening.Bas and SQLitening.Txt.

10. Added a new function called slSelAry which will return a two dimension 
    array containing the column data from all rows.  This will allow you 
    to navigate a record set both forward, backward, and directly.  Sample
    usage is in ExampleC.Bas.

11. Changed the password checking to include read-only access. A password 
    containing the percent sign (%) character will require the file to be opened
    as read-only.

12. Fixed bug in slExeBind.

13. Fixed bug in slGetColumnCount.

14. Added a ReadMe.Txt file in Doc folder.


===================<[ Version 3 -- July 15, 2008 ]>===================

1. Changed slOpen to use the new sqlite3_open_v2 API which was added in 
   version 3.5.0 of SQLite3.  This new open allows for read only and 
   temporary database on disk.  It also creates a new database only if 
   requested.  The temporary database on disk could be very useful
   (still can have the :memory: one). Removed the ModChar S.  It was 
   no loger needed with the new sqlite3_open_v2 API. 

2. Eliminated slIsSetEmpty and slIsRowThere.  These were not clean routines
   and their use could have caused confusion.  Using "if slGetRow" will
   accomplish same results and is much cleaner.

3. Added ModChar of "C" to slGetRow which will close the set even if
   there is another row available.  This has use when all you want
   to do is check if an set has rows. 
      slSel "Select 1 from T1 where Key='ABC'"
      if slGetRow(0, "C") then
         ' has rows action
      else
         ' has no rows action
      end if

4. Changed slIsSetOpen to slIsSetNumberValid to be consistent.

5. Changed slGetChangeCout to use ModChar instead of Flag to be 
   consistent.

4. Added slIsColumnNumberValid and slIsColumnNameValid.  These along with
   slIsSetNumberValid should prevent aborts and allow for more programmer 
   control.

5. Improved performance when checking for valid column number.

6. Added column number, column name, and set number audits to appropriate
   routines to prevent GPFs.  

7. Error number -13 (Invalid column name or number) was added. 

8. Changed SQLitening.Txt to be in alpha sequence rather than by group.


===================<[ Version 2 -- July 7, 2008 ]>====================

1. Eliminated error -13 which was used for Invalid parms.  The current code
   can no longer rais this error.
 
2. Eliminated the slEscapeSpecialChars routine.  It did only one PB replace
   command which replaced all ' with ''.
 
3. Added slIsSetOpen routine.  This was a forum request.
 
4. Enhanced slExeBind so it can bind multiply fields in one call.  It can also 
   encrypt and/or compress a field.
    
5. Enhanced slFX and slFNX to be able to get fields and decrypt and/or uncompress.
 
6. Added the K ModChar to slSetProcessMods which will set/unset the cryption key.
 
7. There is a new Dll called SQLiteningAuxRuts.Dll.  This is were the Rijndael 
   cryption code resides as well as the calls to Zlib for compression.  I added 
   a Dll so there would be no additional memory usage for those that do not use
   cryption nor compression.  This aux dll resides only with the client -- server is 
   not concerned.  Note that the encryption/compression occurs at the field level.
   Not the row nor column level.  So if you encrypt/compress with slExeBind then
   you must also decrypt/uncompress with either slFX or slFNX.  I used Rijndael 
   cause it is much faster and smaller then BlowFish and was selected by the NIST 
   as Advanced Encryption Standard.  Whatever that means but it impressed me.
 
8. Added two new options to the General section of the config file:
      CreateDatabaseAllowed = Yes or No  ---  Controls the creation of new databases.  If Yes then clients are 
                                              allowed to create new databases on the server.  If omitted then 
                                              will default to No
      TrimLogManually = Yes or No  ---  Controls the trimming of the log when it becomes larg e (> 600K).  If Yes 
                                        then no automatic trimming will occur.  If no then will automatically 
                                        trim 100K from front of log when it becomes large. If omitted then will 
                                        default to No
 
9. Enhanced the Adim refresh so it will now refresh the config flags as 
   well as the FACT
 
10. Included a second simple example program which does encryption and compression.
   
11. Enhanced almost all of the routine comments.  The updated comments
    are changed in both SQLitening.Bas and SQLitening.Txt.  This area
    should settle down in future.
 
===================<[ Version 1 -- June 29, 2008 ]>====================

