INI-files and mod harbour

mod_harbour is an Apache module that allows to run PRGs directly on the web !!!

INI-files and mod harbour

Postby Otto » Mon Jan 03, 2022 8:21 am

Hello firends,
A few years ago, I wanted to change my program from INI files to DBF.
At that time, we developed a function to convert INI files to dbf and then to access the keys.
I think it will be easiest if you continue to use the DESKTOP program, INI files online. You are used to so many entries.
/*
GetDBProfString( cSection, cEntry, uDefault, cIniFile )
- Syntax similar to GetPvProfString() function
- If file extention of cIniFile is "ini", then the call is forwarded to GetPvProgString().
So, in - your application you can use this function in the place of GetPvProgString at all places.
- Otherwise this function reads from cIniFile, forcing extention "dbf".
- If the dbf does not exist, returns the default value
- If the dbf exists, then opens the dbf and chceks for the keys
- If the keys exist, returns value from dbf
- Otherwise returns default
WriteDBProfString( cSection, cEntry, uValue, cIniFile )
- Syntax similar to WritePProfString() function
- If file extention of cIniFile is "ini", then the call is forwarded to WritePProfString().
So, in - your application you can use this function in the place of WritePProfString at all places.
- Otherwise this function writes cIniFile, forcing extention "dbf".
- If the dbf does not exist, dbf is created
- Opens the dbf and chceks for the keys
- If the keys exist, updates the value in the dbf
- Otherwise appends a new entry with the values.
EditIniDBF( cDbf )
- If the dbf does not exist and user wants to create, then the dbf is created
- User can edit values and/or append new values.
*/
I am not yet sure whether you should load all INI entries into a hash at program start or if you need an entry/key then simply access the database.
How do you solve the problem with the INI settings in Mod Harbour?

Best regards,
Otto

Code: Select all  Expand view  RUN

#include "fivewin.ch"

/*
GetDBProfString( cSection, cEntry, uDefault, cIniFile )
- Syntax similar to GetPvProfString() function
- If file extention of cIniFile is "ini", then the call is forwarded to GetPvProgString().
  So, in - your application you can use this function in the place of GetPvProgString at all places.
- Otherwise this function reads from cIniFile, forcing extention "dbf".
- If the dbf does not exist, returns the default value
- If the dbf exists, then opens the dbf and chceks for the keys
- If the keys exist, returns value from dbf
- Otherwise returns default

WriteDBProfString( cSection, cEntry, uValue, cIniFile )
- Syntax similar to WritePProfString() function
- If file extention of cIniFile is "ini", then the call is forwarded to WritePProfString().
  So, in - your application you can use this function in the place of WritePProfString at all places.
- Otherwise this function writes cIniFile, forcing extention "dbf".
- If the dbf does not exist, dbf is created
- Opens the dbf and chceks for the keys
- If the keys exist, updates the value in the dbf
- Otherwise appends a new entry with the values.

EditIniDBF( cDbf )
- If the dbf does not exist and user wants to create, then the dbf is created
- User can edit values and/or append new values.
*/


 #define TEST

REQUEST DBFCDX

static hIni    := {=>}

//----------------------------------------------------------------------------//

#ifdef TEST

function Main()

local cDbf := "c:\fwh\samples\xplan_ini.dbf"


EditIniDBF( cDbf )
  /* ? "test"

   ? GetDBProfString( "files", "fields", 23, "rama.dbf" )

   WriteDBProfString( "files", "fields", 77, "rama.dbf" )
   WriteDBProfString( "files", "fields", 99, "ini\ranga.dbf" )

   ? GetDBProfString( "files", "fields", 23, "ini\ranga.dbf" )
*/

return nil

#endif

//----------------------------------------------------------------------------//

function GetDBProfString( cSection, cEntry, uDefault, cIniFile )

   local uRet, cAlias

   cIniFile    := AllTrim( cIniFile )
   if Lower( cFileExt( cIniFile ) ) == "ini"
      return GetPvProfString( cSection, cEntry, uDefault, cIniFile )
   endif
   uRet        := uDefault
   cIniFile    := TrueName( cFileSetExt( cIniFile, "dbf" ) )
   cAlias      := GetIniAlias( cIniFile )

   if .not. Empty( cAlias )

      cSection := LTrim( cSection )
      cEntry   := LTrim( cEntry )

      if ( cAlias )->( DBSEEK( MakeKey( cSection, cEntry ) ) )
         uRet  := ( cAlias )->X_VALUE
         if ValType( uDefault ) == 'N'
            uRet  := Val( uRet )
         endif
      endif
   endif

return uRet

//----------------------------------------------------------------------------//

function WriteDBProfString( cSection, cEntry, uValue, cIniFile )

   local cAlias

   cIniFile    := AllTrim( cIniFile )
   if Lower( cFileExt( cIniFile ) ) == "ini"
      return WritePProString( cSection, cEntry, uValue, cIniFile )
   endif
   cIniFile    := TrueName( cFileSetExt( cIniFile, "dbf" ) )
   cAlias      := OpenIniDBF( cIniFile )

   if ( cAlias )->( DBSEEK( MakeKey( cSection, cEntry ) ) )
      do while !( cAlias )->( DBRLOCK() )
      enddo
      ( cAlias )->X_VALUE  := LTrim( cValToChar( uValue ) )
      DBRUNLOCK()
   else
      do while .t.
         ( cAlias )->( DBAPPEND() )
         if .not. NetErr()
            EXIT
         endif
      enddo
      ( cAlias )->X_SECTION   := LTrim( cSection )
      ( cAlias )->X_KEY       := LTrim( cEntry )
      ( cAlias )->X_VALUE     := LTrim( cValToChar( uValue ) )
   endif

return nil

//----------------------------------------------------------------------------//

function EditIniDBF( cDbf )

   local cAlias

   cDbf  := TrueName( cFileSetExt( cDbf, "dbf" ) )
   if .not. File( cDbf )
      if .not. MsgNoYes( cDbf + " does not exist" + CRLF + ;
                   "Create new DBF?" )
         return nil
      endif
   endif

   cAlias := OpenIniDBF( cDbf )

   XBROWSER cAlias TITLE cDBF FASTEDIT

   // DO NOT CLOSE THE DBF. IT SHOULD REMAIN OPEN

return nil

//----------------------------------------------------------------------------//

static function GetIniAlias( cIniDbf )

   local cAlias

   cIniDBF     := UPPER( cIniDBF )
   if HHasKey( hIni, cIniDbf )
      cAlias   := hIni[ cIniDBF ]
   endif

   if Empty( cAlias ) .and. File( cIniDBF )
      cAlias   := OpenIniDbf( cIniDBF )
   endif

return cAlias

//----------------------------------------------------------------------------//

static function OpenIniDBF( cIniDbf )

   local cAlias

   if .not. ( PROCNAME( 1 ) == "GETINIALIAS" )
      cAlias   := GetIniAlias( @cIniDBF )
   endif
   if Empty( cAlias )
      if .not. File( cIniDBF )
         CreateIniDBF( cIniDBF )
      elseif .not. File( cFileSetExt( cIniDBF, "cdx" ) )
         CreateIniIndex( cIniDBF )
      endif
      cAlias   := cGetNewAlias( "INI" )
      USE ( cIniDBF ) NEW SHARED ALIAS ( cAlias ) VIA "DBFCDX"
      SET ORDER TO TAG SECKEY
      SET FILTER TO !DELETED()
      GO TOP
      hIni[ Upper( cIniDBF ) ] := cAlias
   endif

return cAlias

//----------------------------------------------------------------------------//

static function CreateIniDBF( cDbf )

   field X_SECTION, X_KEY

   local cPath    := cFilePath( cDbf )

   if .not. lIsDir( cPath )
      lMkFullPath( cPath )
   endif

   DBCREATE( cDbf, ;
      {  {  "X_SECTION",   "C",  30,   0  } ,;
         {  "X_KEY",       "C",  30,   0  } ,;
         {  "X_VALUE",     "C", 100,   0  } ,;
         {  "X_COMMENTS",  "C", 200,   0  }  }, ;
      "DBFCDX", .T., "DBINI" )

   INDEX ON UPPER(X_SECTION)+UPPER(X_KEY) TAG SECKEY
   INDEX ON DELETED() TAG DELETED
   CLOSE DBINI

return nil

//----------------------------------------------------------------------------//

static function CreateIniIndex( cDbf )

   field X_SECTION, X_KEY

   USE ( cDBF ) NEW ALIAS "INICDX" EXCLUSIVE VIA "DBINI"
   if .not. USED()
      ? "Can not open " + cDBF + "Exclusively"
      QUIT
   endif
   INDEX ON UPPER(X_SECTION)+UPPER(X_KEY) TAG SECKEY
   INDEX ON DELETED() TAG DELETED
   CLOSE DBINI

return .t.

//----------------------------------------------------------------------------//

static function MakeKey( cSection, cKey )
return PADR( UPPER( LTRIM( cSection ) ), 30 ) + ;
       PADR( UPPER( LTRIM( cKey     ) ), 30 )

//----------------------------------------------------------------------------//





 
********************************************************************
mod harbour - Vamos a la conquista de la Web
modharbour.org
https://www.facebook.com/groups/modharbour.club
********************************************************************
User avatar
Otto
 
Posts: 6364
Joined: Fri Oct 07, 2005 7:07 pm

Re: INI-files and mod harbour

Postby Otto » Mon Jan 03, 2022 9:28 am

This version includes ConvertIniToDBF( cIni ).



Code: Select all  Expand view  RUN

 
#include "fivewin.ch"

/*
GetDBProfString( cSection, cEntry, uDefault, cIniFile )
- Syntax similar to GetPvProfString() function
- If file extention of cIniFile is "ini", then the call is forwarded to GetPvProgString().
  So, in - your application you can use this function in the place of GetPvProgString at all places.
- Otherwise this function reads from cIniFile, forcing extention "dbf".
- If the dbf does not exist, returns the default value
- If the dbf exists, then opens the dbf and chceks for the keys
- If the keys exist, returns value from dbf
- Otherwise returns default

WriteDBProfString( cSection, cEntry, uValue, cIniFile )
- Syntax similar to WritePProfString() function
- If file extention of cIniFile is "ini", then the call is forwarded to WritePProfString().
  So, in - your application you can use this function in the place of WritePProfString at all places.
- Otherwise this function writes cIniFile, forcing extention "dbf".
- If the dbf does not exist, dbf is created
- Opens the dbf and chceks for the keys
- If the keys exist, updates the value in the dbf
- Otherwise appends a new entry with the values.

EditIniDBF( cDbf )
- If the dbf does not exist and user wants to create, then the dbf is created
- User can edit values and/or append new values.

ConvertIniToDBF( cIni )
- Reads ini file, converts to DBF and opens the DBF for edit.
- If the ini file name is "myinifile.ini", dbf name is "myinifile_ini.dbf"
- If successful, returns the name of the dbf file
- On failure returns nil

*/


/*

// TRANSLATES TO INCLUDE IN PRG FILES OF THE PROJECT

#xtranslate WritePProString(   <s>, <e>, <v>, <i> ) => ;
            WriteDBProfString( <s>, <e>, <v>, <i> )

#xtranslate GetPvProfString( <s>, <e>, [<d>], <i> ) => ;
            GetDBProfString( <s>, <e>, [<d>], <i> )

*/


#define TEST

REQUEST DBFCDX

static hIni    := {=>}

//----------------------------------------------------------------------------//

#ifdef TEST

function Main()

   local cIni, cDbf

   ? "Start"

   cIni  := cGetFile( "Ini file(*.ini)|*.ini|", "Select INI file to convert" )
   if !Empty( cIni )
      cDbf := ConvertIniToDbf( cIni )
   endif
 
return nil

#endif

//----------------------------------------------------------------------------//

function ConvertIniToDbf( cIni )

   local cPath, cDbf, cAlias
   local aLines

   cIni     := TrueName( cIni )
   
   
   if !File( cIni )
      ? "File ->" + cIni + "<- not found"
      return nil
   endif

   cPath    := cFilePath( cIni )
   cDbf     := cFileNoExt( cIni )
   cDbf     := cPath + cDbf + "_ini.dbf"

   if File( cDbf )
      if .not. MsgNoYes( cDbf + " already exists" + CRLF + ;
                         "OverWrite?" )
         return nil
      endif
      if FErase( cDbf ) != 0
         ? cDbf + " is in use. Can not be overwritten"
         return nil
      endif
   endif

   aLines   := IniTextAsArray( MEMOREAD( cIni ) )

   CreateIniDBF( cDBF, aLines )
? "DBF Ini wurde erstellt:  " + cDBF
   XBROWSER cDBF TITLE cDbf FASTEDIT
   
    cAlias      := OpenIniDBF( cDbf )
   
    ( cAlias )->( DbGotop() )
    do while .not. ( cAlias )->( eof() )
   
       
         
    WritePProString(  ALLTrim( ( cAlias )->X_SECTION ), ALLTrim( ( cAlias )->X_KEY), ALLTrim( ( cAlias )->X_VALUE ), cIni  )
   
      ( cAlias )->( dbskip() )

   enddo
return cDbf

//----------------------------------------------------------------------------//

function GetDBProfString( cSection, cEntry, uDefault, cIniFile )

   local uRet, cAlias

   cIniFile    := AllTrim( cIniFile )
   if Lower( cFileExt( cIniFile ) ) == "ini"
      return GetPvProfString( cSection, cEntry, uDefault, cIniFile )
   endif
   uRet        := uDefault
   cIniFile    := TrueName( cFileSetExt( cIniFile, "dbf" ) )
   cAlias      := GetIniAlias( cIniFile )

   if .not. Empty( cAlias )

      cSection := LTrim( cSection )
      cEntry   := LTrim( cEntry )

      if ( cAlias )->( DBSEEK( MakeKey( cSection, cEntry ) ) )
         uRet  := ( cAlias )->X_VALUE
         if ValType( uDefault ) == 'N'
            uRet  := Val( uRet )
         endif
      endif
   endif

return uRet

//----------------------------------------------------------------------------//

function WriteDBProfString( cSection, cEntry, uValue, cIniFile )

   local cAlias

   cIniFile    := AllTrim( cIniFile )
   if Lower( cFileExt( cIniFile ) ) == "ini"
      return WritePProString( cSection, cEntry, uValue, cIniFile )
   endif
   cIniFile    := TrueName( cFileSetExt( cIniFile, "dbf" ) )
   cAlias      := OpenIniDBF( cIniFile )

   if ( cAlias )->( DBSEEK( MakeKey( cSection, cEntry ) ) )
      do while !( cAlias )->( DBRLOCK() )
      enddo
      ( cAlias )->X_VALUE  := LTrim( cValToChar( uValue ) )
      DBRUNLOCK()
   else
      do while .t.
         ( cAlias )->( DBAPPEND() )
         if .not. NetErr()
            EXIT
         endif
      enddo
      ( cAlias )->X_SECTION   := LTrim( cSection )
      ( cAlias )->X_KEY       := LTrim( cEntry )
      ( cAlias )->X_VALUE     := LTrim( cValToChar( uValue ) )
   endif

return nil

//----------------------------------------------------------------------------//

function EditIniDBF( cDbf )

   local cAlias

   cDbf  := TrueName( cFileSetExt( cDbf, "dbf" ) )
   if .not. File( cDbf )
      if .not. MsgNoYes( cDbf + " does not exist" + CRLF + ;
                   "Create new DBF?" )
         return nil
      endif
   endif

   cAlias := OpenIniDBF( cDbf )

   XBROWSER cAlias TITLE cDBF FASTEDIT
   
   // DO NOT CLOSE THE DBF. IT SHOULD REMAIN OPEN

return nil

//----------------------------------------------------------------------------//

static function GetIniAlias( cIniDbf )

   local cAlias

   cIniDBF     := UPPER( cIniDBF )
   if HHasKey( hIni, cIniDbf )
      cAlias   := hIni[ cIniDBF ]
   endif

   if Empty( cAlias ) .and. File( cIniDBF )
      cAlias   := OpenIniDbf( cIniDBF )
   endif

return cAlias

//----------------------------------------------------------------------------//

static function OpenIniDBF( cIniDbf )

   local cAlias

   if .not. ( PROCNAME( 1 ) == "GETINIALIAS" )
      cAlias   := GetIniAlias( @cIniDBF )
   endif
   if Empty( cAlias )
      if .not. File( cIniDBF )
         CreateIniDBF( cIniDBF )
      elseif .not. File( cFileSetExt( cIniDBF, "cdx" ) )
         CreateIniIndex( cIniDBF )
      endif
      cAlias   := cGetNewAlias( "INI" )
      USE ( cIniDBF ) NEW SHARED ALIAS ( cAlias ) VIA "DBFCDX"
      SET ORDER TO TAG SECKEY
      SET FILTER TO !DELETED()
      GO TOP
      hIni[ Upper( cIniDBF ) ] := cAlias
   endif

return cAlias

//----------------------------------------------------------------------------//

static function CreateIniDBF( cDbf, aData )

   field X_SECTION, X_KEY

   local cPath    := cFilePath( cDbf )

   if .not. lIsDir( cPath )
      lMkFullPath( cPath )
   endif

   DBCREATE( cDbf, ;
      {  {  "X_SECTION",   "C",  100,   0  } ,;
         {  "X_KEY",       "C",  100,   0  } ,;
         {  "X_VALUE",     "C", 200,   0  } ,;
         {  "X_COMMENTS",  "C", 200,   0  }  }, ;
      "DBFCDX", .T., "DBINI" )

   INDEX ON UPPER(X_SECTION)+UPPER(X_KEY) TAG SECKEY
   INDEX ON DELETED() TAG DELETED
   if !Empty( aData )
      DBINI->( FW_ArrayToDBF( aData ) )
   endif
   CLOSE DBINI

return nil

//----------------------------------------------------------------------------//

static function CreateIniIndex( cDbf )

   field X_SECTION, X_KEY

   USE ( cDBF ) NEW ALIAS "INICDX" EXCLUSIVE VIA "DBINI"

   if .not. USED()
      ? "Can not open " + cDBF + "Exclusively"
      QUIT
   endif
   INDEX ON UPPER(X_SECTION)+UPPER(X_KEY) TAG SECKEY
   INDEX ON DELETED() TAG DELETED
   CLOSE DBINI

return .t.

//----------------------------------------------------------------------------//

static function MakeKey( cSection, cKey )
return PADR( UPPER( LTRIM( cSection ) ), 30 ) + ;
       PADR( UPPER( LTRIM( cKey     ) ), 30 )

//----------------------------------------------------------------------------//

static function IniTextAsArray( cText )

   local aLines, tmp, n, cLine
   local cSection, aLine, c1, c2

   cText    := StrTran( cText, CRLF, Chr( 10 ) )
   aLines   := HB_ATokens( cText, Chr( 10 ) )
   AEval( aLines, { |c,i| aLines[ i ] := AllTrim( c ) } )
   tmp      := {}
   AEval( aLines, { |c| If( Empty( c ), nil, AAdd( tmp, c ) ) } )

   aLines   := {}
   for each cLine in tmp
      if left( cLine, 1 )  == "[" .and. ;
         Right( cLine, 1 ) == "]"

         cSection := CharRem( "[]", cLine )
      else
         if "=" $ cLine
            c1    := Trim(  BeforAtNum( "=", cLine, 1 ) )
            c2    := LTrim( AfterAtNum( "=", cLine, 1 ) )
         else
            c1    := cLine
            c2    := ""
         endif
         AAdd( aLines, { cSection, c1, c2, "" } )
      endif
   next

return aLines

//----------------------------------------------------------------------------//

/*
#xtranslate WritePProString(   <s>, <e>, <v>, <i> ) => ;
            WriteDBProfString( <s>, <e>, <v>, <i> )

#xtranslate GetPvProfString( <s>, <e>, [<d>], <i> ) => ;
            GetDBProfString( <s>, <e>, [<d>], <i> )
*/



 
********************************************************************
mod harbour - Vamos a la conquista de la Web
modharbour.org
https://www.facebook.com/groups/modharbour.club
********************************************************************
User avatar
Otto
 
Posts: 6364
Joined: Fri Oct 07, 2005 7:07 pm

Re: INI-files and mod harbour

Postby Otto » Mon Jan 03, 2022 1:01 pm

Here you see how you can address the values from
mod harbour
hINI["SETUPDATEN-DATEN"]
JAVASCRIPT
oini["SETUPDATEN-DATEN"]
HTML
<?prg return hINI["SETUPDATEN-DATEN"]?>

Image

Code: Select all  Expand view  RUN



REQUEST DBFCDX
REQUEST DBFFPT

function main
    local hINI := {=>}
    local cdbf_file := hb_GetEnv( "PRGPATH" ) + "\ini\winhotel_ini.dbf"
   
    hINI := dbf2hash( cdbf_file )
    ? "hier sehen wir den Wert von mod harbour aus " + hINI["SETUPDATEN-DATEN"]
    TEMPLATE PARAMS hINI
<!DOCTYPE html>
<html>
<head>
    <style>
        body {background-color: powderblue;}
        h1   {color: blue;}
        p    {color: red;}
    </style>
</head>
<body>
    <script>
        var oini=<?prg return hb_jsonEncode( hINI, .T. )?>;
        alert(oini["SETUPDATEN-DATEN"]);
    </script>
    <h1>This is a heading</h1>
    <p>This is a paragraph.</p>
    <H1> Das ist das Datenverzeichnis <?prg return hINI["SETUPDATEN-DATEN"]?> </H1> <br>
</body>
</html>
ENDTEXT
return
//----------------------------------------------------------------------------//
function dbf2hash( cdbf_file )
    local hDBF_Recs
    local nDBF_RecRead := 0
    *------------------------------------------------------------------------------
    hDBF_Recs := {=>}
    use ( cdbf_file ) new ALIAS TMPDBF_FILE
    do while .not. eof()
        nDBF_RecRead += 1
        if LEN( ALLTRIM( TMPDBF_FILE->X_VALUE ) ) = 0
            hDBF_Recs[  UPPER( ALLTRIM( TMPDBF_FILE->X_SECTION )  +"-" + ALLTRIM( TMPDBF_FILE->X_KEY ) )] = "-"
        else
            hDBF_Recs[   UPPER( ALLTRIM( TMPDBF_FILE->X_SECTION )  +"-" + ALLTRIM( TMPDBF_FILE->X_KEY ) )]  =   ALLTRIM( TMPDBF_FILE->X_VALUE )
        endif
        select TMPDBF_FILE
        skip
    enddo
    select TMPDBF_FILE
    use
    hDBF_Recs[ "RECREAD" ] := str( nDBF_RecRead + 1 )
return( hDBF_Recs )
//----------------------------------------------------------------------------//
INIT PROCEDURE PrgInit
   
    SET CENTURY ON
    SET EPOCH TO YEAR(DATE())-98
    SET DELETED ON
    SET EXCLUSIVE OFF
    REQUEST HB_Lang_DE
    HB_LangSelect("DE")
    SET DATE TO GERMAN
    rddsetdefault( "DBFCDX" )
    EXTERN DESCEND
   
RETURN

//----------------------------------------------------------------------------//

 
********************************************************************
mod harbour - Vamos a la conquista de la Web
modharbour.org
https://www.facebook.com/groups/modharbour.club
********************************************************************
User avatar
Otto
 
Posts: 6364
Joined: Fri Oct 07, 2005 7:07 pm


Return to mod_harbour

Who is online

Users browsing this forum: No registered users and 5 guests