MariaDb verbinding zonder SSL

Cannot open database: TLS/SSL error: SSL is required, but the server does not support it

Sinds ongeveer OpenSUSE v. 15.6 à 16.0 dook het probleem op dat Gambas3 programma’s geen verbinding meer konden maken met een bestaande mariadb database op een computer in het lokaal netwerk, zonder SSL (zie Database verbinding gebroken). Ik vond het probleem niet bij Raspbian (Debian), voor andere distributies weet ik niet, misschien Red Hat?

Het probleem was terug te brengen tot de stap naar een nieuwe mariadb client lib:

libmariadb3 v. 3.4.5

… waarbij het standaard gedrag van de MariaDB Connector/C 3.4 veranderde.

De gewone “skip-ssl” volstaat niet meer (Unable to disable TLS verification when using mariadb-connector-c >= 3.4.0).

Dit kan voor allerlei software die dit soort databaseverbinding maakt een fout/verandering opleveren; openoffice/libreoffice, python programma’s, …. niet alleen voor Gambas.

Omzeilen

Voor Gambas3 kan je het probleem omzeilen door een combinatie van

  • instellingen in een mariadb configuratiebestand op de client computer (waar het gambas programma draait)
  • aanroepen van de juiste opties vanuit je code voor het maken van de verbinding.

Mariadb client configuratie

De instellingen gebeuren normaal in het onzichtbare bestand .my.cfg in de home directory van de gebruiker:

~/.my.cfg

Daarin staat misschien al de instelling om op de CLI de SSL te omzeilen:

[client]
skip-ssl = true

Maak een nieuwe paragraaf aan, bv met de titel “gambasfixnossl” (nadien moet je naar deze header verwijzen in je code):

[gambasfixnossl]
ssl-verify-server-cert=0
ssl-mode=DISABLED

Gambas3 connection opties

Je hebt een combinatie van connection opties nodig om de fout te vermijden. Dit stond al in mijn code*:

With hConnection
.Host = Settings["Connection/Host"]
.User = Settings["Connection/User"]
.Name = Settings["Connection/Name"]
.Password = Settings["Connection/Password"]
.Type = Settings["Connection/Type", "mysql"]
End With

En dit heb ik er nu bijgevoegd:

  ...
.Options["READ_DEFAULT_GROUP"] = "gambasfixnossl"
.Options["PROTOCOL"] = 1
.Options["SSL_MODE"] = 0
.Options["SSL"] = False
.Options["CLIENT_FLAGS"] = 0
.Options["MYSQL_OPT_SSL_ENFORCE"] = 0
End With

Getest

  • Werkt op openSUSE Leap 16.0
  • Werkt op Tumbleweed 20251013

Nota’s: (*) Settings gebruik, Apart mariadb configuratiebestand, .. Continue reading

Bladwijzer in de broncode (bookmark)

Als je een probleem in de broncode aan het oplossen bent, moet je kunnen heen en weer springen tussen verschillende stukken code. Daarvoor kan je een bladwijzer zetten om je vorige positie te onthouden: sta op een lijn en druk Ctrl-B. Er verschijnt een zacht (lichtblauw bij mij) pijltje voor de lijn.

Ga naar een willekeurige andere lijn in je text (als je weet dat je rond 500 bezig was, druk Ctrl-G 500.

Ga nu snel terug naar je bookmark met Alt-PageUp of Alt-PageDown.

Dat is handiger dan er breekpunten voor te gebruiken, die kunnen later hinderen.

Gambas en GPIO op Raspberry Pi

Een poging om commandline gpio te gebruiken vanuit/om te leiden naar een Gambas programma.

Library "/user/local/libpigpio"

Public Sub testGPIO()

Dim sAnswer As String
Dim sCommand As String

sCommand = "gpio -h"

TRY SHELL sCommand TO sAnswer

TextAreaOut.Text = sAnswer

End

Ik ga er van uit dat je een Form hebt, FMain, waar je deze code in plakt.

Op de Form heb je een TextAreaOut gemaakt.

Je kan op het scherm dan een button zetten, die deze code aanroept.

Public Sub Button1_Click()

testGPIO()

End

Hetzelfde kan je doen met gpio -g readall in sCommand; dat leest de pinnen uit naar een tabel met informatie en pin-nummers (incl BCM nummers). Enz…

Compileren met debug info

Soms kan het nuttig zijn om je programma te compileren mét de debug informatie aan, het is een parameter die je kan instellen in de IDE.

In een script: parameter -g bij de opdracht gbc:

gbc3 -g -a 2> log.txt

gevolgd door

gba3 -o $targetdir/gb3run/$targetbase.gambas

Vriendelijk afsluiten van je programma

Een voorbeeldje van wat in mijn MMain zit bij een programma met meer vensters
(in de Gambas IDE zijn dat de Forms):

Public Sub doQuit()
  '
  Dim hWindow As Window
  '
  Settings.Save  ' other code 
  hRunCounter.appClose() ' other code
  For Each hWindow In Windows
    hWindow.Close
  Next
  '
End

Other code:
Settings.Save: omdat ik de component Settings gebruikt.
hRunCounter: ik hou een teller bij van het starten en sluiten van het programma

Git vanuit gambas

Voor een eigen programma waar de inhoud wordt bijgehouden in een git repository, zou ik die willen kunnen updaten vanuit mijn Gambas app. Sinds een tijdje is in de IDE een voorziening ingebouwd om de git branch om te schakelen enz vanuit de IDE, dus daar zit mogelijk een aanknooppunt.

Algemeen: een commando kan je vanuit Gambas lanceren met shell of exec.

In de broncode van gambas 3.18.0 vind je een map VersionControl met een Class CVersionControl, met een subclass CVersionControlGit.

Daarin:
Private Sub RunShell(sCmd As String, Optional bSilent As Boolean) As String
'
Return VersionControl.Shell("cd " & Shell(Project.Dir) & " && " & sCmd, bSilent)
'
End

In de Module (naam zonder M) “VersionControl” vind je:

Public Sub Shell(sCmd As String, Optional bSilent As Boolean, Optional aEnv As String[]) As String
'
Dim sResult As String
'
If Not bSilent Then Insert(sCmd & "\n")
Shell sCmd With aEnv To sResult
If Process.LastValue Then
$sLastResult = sResult
Insert(sResult)
Endif
Return sResult
'
End

Testen van database verbinding

Foutmelding als “System error 110” vanuit sql zijn soms veroorzaakt door een slechte/trage verbinding.
Best maak je een standaard db-test project dat niets doet behalve de verbinding testen, en dan kan je dat steeds weer gebruiken.

Is de database verbinding nog ok?

  • Database gegevens initialiseren.
  • Database verbinding openen
  • …loop van het programma dat gegevens gebruikt
  • Database verbinding sluiten

Het probleem dat hier kan optreden is de duur dat de databaseverbinding open blijft. Hoe langer het programma draait, hoe meer kans dat de database op een bepaald moment niet bereikbaar is. Typisch is na het blijven openstaan gedurende de nacht; eerste handeling de volgende dag doet het programma crashen als de databasefouten niet juist worden opgevangen.
Het alternatief kan zijn bij elke aktie op de database de verbinding te openen en te sluiten.
Of de verbinding te testen en indien niet meer goed, te heropenen.

Hoe best de procedures maken in de Data module?

Je kan een “result” teruggeven, die kan verder verwerkt worden in de aanroepende code:

PUBLIC SUB getWorkedOn(sWork AS String) AS Result
'  
  DIM myResult AS Result
  DIM sSql AS String
'  
  sSql = "SELECT * FROM reg "
  sSql &= "WHERE reg_type='U' AND ord_code = &1 "
'  
  TRY myResult = $hConNoxqs.Exec(sSql, sWork)
'  
  IF ERROR 
    sLastError = Error.Text
    RETURN NULL
  ELSE 
    RETURN myResult 
  ENDIF 
'
END

Of je kan een waarde teruggeven:

PUBLIC SUB getEmployeeCount() AS Integer
'
  DIM iMonthNames AS Integer
'
  $hResEmployees = MData.getEmployees(MCommon.bActiveOnly)
'
  iMonthNames = $hResEmployees.Count
  SetLog("Employees used: " & iMonthNames & ", active employees: " & Str$(MData.activeEmployees("A")))
'
  RETURN iMonthNames
'
END

Checklist nieuw project, hulpmiddelen

update van gambas.copyleft.be/blog/checklist-project van 2014/2017

Start een nieuw project: commandolijn, lib, grafisch, databank, …
Algemeen: gebruik settings, foutbeheer, log, versienummer, ..

commandolijn

  • ook te gebruiken als shell script. Let op met locatie van bestanden/de applicatie zelf.

commandolijn, lib, grafisch, databank

lib

  • hergebruik in diverse projecten. Opgelet voor versie-verschillen…
  • locatie: gecompileerde library komt bv terecht in /home/username/.local/share/gambas3/lib/

commandolijn, lib, grafisch, databank

databank:

  • Begin met emptydb project sjabloon
  • Gebruik settings om databankgegevens op te slaan; gebruik een “switch” om tussen test en productiedatabank te wisselen (DataContext).
  • Gebruik een applicatie-log (errorlog) bv myLog
  • Veldnamen conventies
  • meta-informatie; bv in databank met aparte tabel (zie dbinfocode)
  • db struktuur opnemen in project (dump zonder data); opvolging van wijzigingen aan databank struktuur: schrijf telkens een stukje code alvorens/om die wijziging uit te voeren zodat je die kan meenemen.
  • persistence, schermcode genereren, …?

commandolijn, lib, grafisch, databank

Desktop (grafische gebruikers-bediening):

  • Begin met empty project sjabloon.
  • ! desktop-eigen bibliotheken (kde-qt/gtk)
    • worden soms niet meer ondersteund in een volgende versie; bv qt upgrades enz.
    • maken het moeilijker over te zetten naar een andere desktop/distributie..
  • Log: Gebruik een applicatie-log (errorlog) bv myLog
  • Gebruik settings om gebruikersinstellingen op te slaan, bv met GbSettingsTool kan je die vullen/lezen
  • Gebruiksteller of RunCounter: bewaren in settings
  • Venster-titel: Geef nuttige/relevante venstertitels, zodat je ziet welke vensters bij deze applicatie horen; met applicatienaam-vensternaam(functie)-versie.nr, … Bv door procedure in mmain of MForm die je voor elk venster aanroept, met een bDeveloper switch kan je als developer de form naam krijgen, gebruiker krijgt functietitel
  • Venster-icoon: zetten in de form Me.Icon of neem dat eventueel mee op in de procedure van de venstertitel. Je kan het icoon laten evolueren (kleur, scherpte, vorm) om de graad van de hiërarchie van het venster te tonen; bv hoofdvenster, 1e sub, sub-van-1e-sub… Iconen in mapje met namen voor level; iconL0.png ,iconL1.png, iconL2.png, …
  • Menu Help/About met Help, About, License, Changes, WhatsNew,
  • Menu File met Quit die afsluitprocedure oproept. Eventueel per vergissen sluiten met venster [x] opvangen.
  • Feedback naar gebruiker: eventueel te sluiten, of met bDeveloper switch te aktiveren
  • Versienummer: je moet kiezen om die door Gambas te laten tellen of uit een “VERSION” bestand in te lezen. Je kan dat versienummer ook bij verhogen van de gebruiksteller opslaan als laatstgebruikte versie in het settingsbestand.
  • Weergaveconventies: stel op en gebruik, integreer in een voorbeeldscherm. Kleur/vorm voor vaste tekst, ingaveveld, ingavevoorbeeld, reaktie, foutmelding, enz.
  • Dubbelstartcontrole (als dat belangrijk is voor je app – bv omdat die naar een bestand schrijft, ..)

commandolijn, lib, grafisch, databank

Databank toegang aanpassen aan situatie

Databank toegang
Ik gebruik van in mijn Gambas programma een databank (type mysql/mariadb), waarvoor ik over het netwerk inlog naar de databank.
Ik moet de instellingen ergens bewaren; Gambas heeft daarvoor zijn “Settings” in een configuratie-bestand. Daarin bewaar ik server-adres, login, wachtwoord en databanknaam. Mijn toepassing kan verschillende databanken aanspreken, ik noem die “datasets”

Dataset
De dataset situeert zich op een server en heeft zelf als eigenschappen dat ze een naam en een omschrijving heeft.
Voorbeeld van enkele datasets die ik gebruik:

  • pers : personeelsdossiers
  • reg: tijdsregistratie (tikklokken)
  • crm: klantengegevens-databank
  • gitin: it-inventaris

De korte naam wordt intern gebruikt, bv in programma’s en documentatie.

Andere server?
Terwijl ik de applicatie ontwikkel, wil ik niet op de “goede” databank werken, om die data niet te beschadigen, eventueel is dat ook een andere server.
Ik kan andere instellingen gebruiken (bewaard in het configuratie bestand).

Ontwikkel-test-gebruik
Op het moment dat ik wil testen op de goede data, moet ik ofwel het configuratie bestand verwisselen voor een andere versie, of – en dat zou nog handiger zijn – omschakelen in mijn toepassing zelf. In mijn programma zou ik moeten kunnen kiezen voor de databanken van de ontwikkeling, die om te testen, of de echt gebruikte databank “in productie”.

Onderweg – ter plaatse
Die drie verschillende “omgevingen” noem ik de DataContext. Die DataContext kan ook nog verschillen op een andere manier: als ik op mijn laptop werk, offline van mijn productieomgeving, wil ik een lokale kopie op de “localhost” gebruiken (en moet ik daar gemakkelijk naar kunnen overschakelen). Als ik dan op het werk kom, schakel ik over naar de productie-databank, dus hier zijn het eerder verschillende “situaties”.

DataContext
Ik wil dus omschakelen tussen
* Voorbeeld 1:

  1. mobiel (laptop met localhost server)
  2. ter plaatse (server op netwerk)

* Voorbeeld 2:

  1. ontwikkeling (“development”)
  2. test
  3. in gebruik (“in production”)

Instellingen
In mijn instellingen wil ik dus voor een verbinding de combinaties kunnen maken van de datacontext en de dataset (“DataContextX-Dataset”, ofwel de “Connection” gegevens).
Datacontext-Dataset
In het config bestand ziet dat er zo uit:

[DataContext0-Crm]
host="server.domain.tld"
login="myname"
password="qsdljfsdfjqsdljjdsqf"
database="crm"

Ik kan heel flexibel een andere verbindings-combinatie maken voor mijn laptopwerk:

[DataContext1-Crm]
host="localhost"
login="myname"
password="oupotykhlvkhsjhf"
database="crm"

Om aan te geven waarvoor de DataContext0 of DataContext1 staat, definieer ik dat ook in de instellingen:

[DataContext0]
Name="production"
Description="Ter plaats op het werk"


[DataContext1]
Name="mobile"
Description="laptop localhost kopie databank"

En ook over de datasets kan ik die informatie bijhouden:

[DataSet]
Pers="personeelsgegevens"
Reg="tijdsregistratie"
Crm="klanten bestanden"

De dataset kan in een module of library gedefinieerd zijn als constante string:

ModCrm
Public csDATASET as String = "Crm"
Public hConData as Connection
...

Het bewaren in de instellingen en het terug ophalen kan je systematisch doen door daar een “libary” DataContext voor te maken, waardoor dat ook altijd op dezelfde manier gebeurt, en met dezelfde syntax. De library maak je in Gambas als library project, en als uitvoerbaar programma kan die als libarary gebruikt worden in een ander project.

CDataContext
De klasse CDataContext moet aanbieden:
– nieuwe datacontext maken (met naam en beschrijving gegeven)
– nieuwe dataset maken (met naam en beschrijving)
– opvragen van de beschrijving van een gegegven dataset of datacontext
– context kiezen/instellen (vanaf dan wordt gekozen context gebruikt als “huidige”)
– bewaren van nieuwe instellingen voor een datacontext, dataset en connection
– verbinding maken met de databank van een gegeven dataset voor een gegeven connection (met “huidige” context)
– opvragen van allerlei informatie over de bewaarde verbindingen, bv of een bepaalde bestaat, hoeveel er zijn, of de lijst van …

Zie ook Datacontext voor Directory en Datacontext voor directory voorbeeld

Demo in je Form

Ik heb een grappige manier gevonden om iets te demonstreren in je Gambas3 programma.
Ik heb in het “Help” menu (of ? menu) naast About, What’s new, Licentie, Help, enz een item bijgemaakt: Demo.
Ik laat daarbij op het scherm, in volgorde, oplichten wat een gebruiker achtereenvolgens moet doen.
Oplichten doe ik door tijdelijk een (achtergrond-)kleurtje te geven, bv geel. Na een kleine wachttijd van 2 seconden (die gemakkelijk kan aangepast worden in de code – misschien moet ik het instelbaar maken voor de gebruiker), krijgt het voorwerp terug de normale kleur.

mniHelpDemo_Click()
'
Dim iWaitABit as integer = 2
'
'...
'
Button1.Background = Color.Yellow
'
Wait iWaitABit
'
Button1.Background = Color.Background
'
Tabstrip1.index=4
'
Tabstrip1.Background = Color.Yellow
'
Wait iWaitABit
'
Tabstrip1.Background = Color.Background
'
Textbox1.Background = Color.Yellow
'
Wait iWaitABit
'
Textbox1.Background = Color.Background
'
'
combobox1.Background = Color.Yellow
'
combobox1.Popup
'
Wait iWaitABit
'
' combobox1.Popdown - doesn't exist? *
'
combobox1.Background = Color.Background
'
' etc...

* Combobox sluiten
Het enige wat niet goed werkt is dat ik een combobox (rolluikje met keuzes) wel kan openen om te tonen wat er allemaal in staat, maar ik kan het niet sluiten zonder een keuze te maken. Dit was niet voorzien in Gambas3, maar zal er aan toegevoegd worden vanaf de volgende versie.
Het is al opgenomen in de broncode, in commit:
https://gitlab.com/gambas/gambas/-/commit/9d08d1371982221fe876fb29ea12d020d2dd264b

Commit 9d08d137
authored 4 days ago by Benoît Minisini’s avatar Benoît Minisini
ComboBox: Close() is a new method that closes the ComboBox popup.

[GB.QT4]
* NEW: ComboBox: Close() is a new method that closes the ComboBox popup.

[GB.QT5]
* NEW: ComboBox: Close() is a new method that closes the ComboBox popup.