Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
3fb7e59
Replace mysql_real_escape_string with mysqli_real_escape_string
mrysav Jun 8, 2025
8e20b5a
Convert remaining usages to mysqli_ functions except uilog
mrysav Jun 8, 2025
5f8dbba
Fix uses of mysql_error without connection
mrysav Jun 8, 2025
929e029
Make status argument in getByReportingStatus optional to conform with…
mrysav Jun 8, 2025
4bd64ea
Be explicit about using $DB_PORT
mrysav Jun 19, 2025
b237a9c
Add Analytics - remove later
mrysav Aug 12, 2025
b5d7a5c
Fix regression when exporting to excel
mrysav Aug 17, 2025
504b816
Upgrade monolog to 2.x - PHP 7 version
mrysav Aug 30, 2025
436a48c
PHP to 7.4
mrysav Aug 18, 2025
d0e2f82
Fix monolog warn to warning
mrysav Aug 31, 2025
05df927
WIP, no publish
mrysav Sep 15, 2025
3316004
Add backup encryption with libsodium;
mrysav Sep 21, 2025
7e6b685
Encryption and decryption with sodium works
mrysav Sep 24, 2025
94a79be
Fixes for running on Windows
mrysav Oct 8, 2025
c492b4f
Remove php-sodium dependency since 7.4+ includes it
mrysav Oct 8, 2025
d572a31
Merge branch 'master' into unstable
mrysav Dec 21, 2025
061d196
Merge branch 'master' into unstable
mrysav Dec 21, 2025
f9c18b4
Merge branch 'main' into unstable
mrysav Dec 28, 2025
841882a
Merge branch 'main' into unstable
mrysav Jan 5, 2026
f66d3df
Merge branch 'main' into unstable
mrysav Mar 8, 2026
8ab9458
Remove testing files
mrysav Mar 8, 2026
c3be97e
Reset local
mrysav Mar 8, 2026
d988028
Reset local
mrysav Mar 8, 2026
06be3b0
Remove out.key
mrysav Mar 8, 2026
ea43d30
Remove old analytics
mrysav Mar 8, 2026
6f84bb5
gitignore update
Tjones1701 Feb 22, 2026
818ed8b
Initial upgrade and short open tags fixed
Mar 3, 2026
e79b1dd
fixed short open tags
Mar 3, 2026
b2d0432
Add New Patient Bug Fix. Documented under docs folder for docs/C4G_Sp…
Tjones1701 Mar 4, 2026
c5d5a62
fix an issue
Mar 5, 2026
76d20a4
fixing an issue with add patient
Mar 6, 2026
f6e2fd2
fixing an issue
Mar 7, 2026
e0a565a
Adds bug fixes
hakiatalov Mar 7, 2026
8cdf82c
Revert unnecesary changes
hakiatalov Mar 7, 2026
e2547e6
Documentation and fix of the excel bug
Tjones1701 Mar 11, 2026
7a5b0b5
Switch build runner to ubuntu-latest with bash
hakiatalov Mar 16, 2026
edc0748
Add basic version file
hakiatalov Mar 16, 2026
9cd361b
Restructure standalone zip to match HLD directory layout
hakiatalov Mar 16, 2026
0915d54
Copying mysql data directory
hakiatalov Mar 16, 2026
f75052b
Add update payload as separate artifact
hakiatalov Mar 18, 2026
9153826
Add state tracking file
hakiatalov Mar 23, 2026
510997e
Update local path references
hakiatalov Mar 23, 2026
41ce3f7
Merge remote-tracking branch 'origin/PHP-7-Upgrade' into s2026-gha-pe…
hakiatalov Mar 26, 2026
85f133d
Refactor logo handling to use STORAGE_DIR for consistent logo path ma…
hakiatalov Mar 27, 2026
855ebe9
Refactor backup handling to utilize environment variables for directo…
hakiatalov Mar 27, 2026
52b1138
Refactor export_pdf.php to use STORAGE_DIR for exports directory and …
hakiatalov Mar 27, 2026
c3abc20
name change
hakiatalov Mar 27, 2026
e01350d
Refactor createconfigfile.php to create the BLISInterfaceClient direc…
hakiatalov Mar 27, 2026
0a166fe
Refactor key management to ensure keys are moved to the data director…
hakiatalov Mar 27, 2026
93cb3df
Merge remote-tracking branch 'origin/main' into s2026-htdocs-storage
hakiatalov Mar 27, 2026
7b50736
Merge remote-tracking branch 'origin/main' into s2026-gha-peer-eval
hakiatalov Mar 27, 2026
4b1b308
Refactor backup handling to use DATA_DIR for storage paths and improv…
hakiatalov Mar 28, 2026
397f3a9
Change log level from warn to debug for unresolved lab_config_id logging
hakiatalov Mar 28, 2026
37f8c30
Refactor exportLabConfiguration.php to use DATA_DIR for temporary and…
hakiatalov Mar 28, 2026
e0a7819
Remove silent failure case
hakiatalov Mar 31, 2026
d2fc9fb
Remove db migration during backup
hakiatalov Mar 31, 2026
e17f48f
Revert file write for equipment config
hakiatalov Mar 31, 2026
d675cb0
Support multiple image formats
hakiatalov Apr 1, 2026
1160ce7
Refactor path creation
hakiatalov Apr 1, 2026
a88b787
Remove redundant mime mapping
hakiatalov Apr 2, 2026
f988b90
Merge pull request #199 from C4G/s2026-htdocs-storage
hakiatalov Apr 2, 2026
a6c0adc
Merge remote-tracking branch 'origin/main' into feature/s2026-self-up…
hakiatalov Apr 2, 2026
6fd6dce
Revert "Merge remote-tracking branch 'origin/PHP-7-Upgrade' into s202…
hakiatalov Apr 8, 2026
b2991f4
Unify upload-artifact action version from v7 to v4
hakiatalov Apr 8, 2026
3415d63
Adding version input and validation
hakiatalov Apr 9, 2026
8513532
Merge remote-tracking branch 'origin/main' into feature/s2026-self-up…
hakiatalov Apr 18, 2026
0ff1f4b
Merge branch 'feature/s2026-self-update' into unstable
hakiatalov Apr 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
insert_final_newline = true

[*.blis]
insert_final_newline = false
155 changes: 140 additions & 15 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,32 @@ on:
required: true
default: 'main'
type: string
include_launcher:
description: 'Include BLIS-NG.exe in update zip (Stage 1 payload)'
required: false
default: true
type: boolean
include_server_runtime:
description: 'Include server/ binaries in update zip'
required: false
default: true
type: boolean
version:
description: 'Release version (SemVer format, e.g. 4.1.0, 4.1.0-beta.1, 4.1.0-beta.1-hotfix). Do not include a leading "v".'
required: true
type: string
push_tag:
description: 'Create and push git tag to BLIS repo after build'
required: false
default: false
type: boolean

permissions:
contents: write

jobs:
build:
runs-on: windows-latest
runs-on: ubuntu-latest

steps:
- name: Checkout BLIS
Expand Down Expand Up @@ -55,31 +77,134 @@ jobs:
cache: true
cache-dependency-path: 'BLIS-NG/packages.lock.json'

- name: Compute Version
id: versioning
shell: bash
run: |
# Strip whitespace and an accidental leading v/V
VERSION="${{ inputs.version }}"
VERSION="${VERSION#[vV]}"

# Validate: MAJOR.MINOR.PATCH with optional -prerelease and optional -suffix
# Each numeric component must be 0 or a positive integer with no leading zeros.
SEMVER_RE='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[A-Za-z0-9]+(\.[A-Za-z0-9]+)*(-[A-Za-z0-9]+(\.[A-Za-z0-9]+)*)?)?$'
if [[ -z "$VERSION" ]]; then
echo "ERROR: version input is empty." >&2
exit 1
fi
if ! [[ "$VERSION" =~ $SEMVER_RE ]]; then
echo "ERROR: '$VERSION' is not a valid SemVer version." >&2
echo "Expected format: MAJOR.MINOR.PATCH[-prerelease[-suffix]] e.g. 4.1.0 or 4.1.0-beta.1 or 4.1.0-beta.1-hotfix" >&2
exit 1
fi

TAG_NAME="v${VERSION}"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "tag_name=${TAG_NAME}" >> "$GITHUB_OUTPUT"
echo "Validated version: ${VERSION} (tag: ${TAG_NAME})"

- name: Generate version.json
shell: bash
run: |
cat > BLIS/version.json << EOF
{
"version": "${{ steps.versioning.outputs.version }}",
"build_timestamp": "$(date -u +%Y%m%d-%H%M%S)",
"git_sha": "$(git -C BLIS rev-parse --short HEAD)",
"min_launcher_version": "1.0.0"
}
EOF

- name: Verify version.json
shell: bash
run: cat BLIS/version.json

- name: Build BLIS-NG
working-directory: ./BLIS-NG
run: dotnet publish -r win-x64 -c Release

- name: Prepare Artifact Folders
shell: bash
run: |
mkdir BLIS-Standalone

# Copy BLISRuntime (excluding .git)
Copy-Item "./BLISRuntime/*" -Destination "./BLIS-Standalone/" -Recurse -Exclude ".git"

# Copy BLIS (excluding .git and the legacy EXEs)
Copy-Item "./BLIS/*" -Destination "./BLIS-Standalone/" -Recurse -Exclude ".git"
Remove-Item "./BLIS-Standalone/BLIS.exe" -ErrorAction SilentlyContinue
Remove-Item "./BLIS-Standalone/BLIS.exe.manifest" -ErrorAction SilentlyContinue

# Copy BLIS-NG executable
Copy-Item "./BLIS-NG/bin/Release/net10.0/win-x64/publish/BLIS-NG.exe" -Destination "./BLIS-Standalone/"
VERSION=$(python3 -c "import json; print(json.load(open('BLIS/version.json'))['version'])")

mkdir -p BLIS-Standalone/releases/${VERSION}
mkdir -p BLIS-Standalone/local
mkdir -p BLIS-Standalone/storage
mkdir -p BLIS-Standalone/data/backups
mkdir -p BLIS-Standalone/log
mkdir -p BLIS-Standalone/staging

# Application files into the versioned release directory
cp -r ./BLIS/htdocs BLIS-Standalone/releases/${VERSION}/
cp -r ./BLIS/db BLIS-Standalone/releases/${VERSION}/
cp -r ./BLIS/vendor BLIS-Standalone/releases/${VERSION}/
cp -r ./BLIS/local BLIS-Standalone/releases/${VERSION}/
cp ./BLIS/version.json BLIS-Standalone/releases/${VERSION}/

# Working config (copy of defaults)
cp -r ./BLIS/local/* BLIS-Standalone/local/

# Server runtime binaries only
cp -r ./BLISRuntime/server BLIS-Standalone/

# Data directory
cp -r ./BLISRuntime/dbdir BLIS-Standalone/

# Launcher at the root
cp ./BLIS-NG/bin/Release/net10.0/win-x64/publish/BLIS-NG.exe BLIS-Standalone/

# Initial state.json pointing to this release
cat > BLIS-Standalone/state.json << EOF
{
"active_version": "${VERSION}",
"previous_version": null
}
EOF

- name: Create Zip Archive
run: |
Compress-Archive -Path "BLIS-Standalone/*" -DestinationPath BLIS-Standalone.zip
cd BLIS-Standalone && zip -r ../BLIS-Standalone.zip . && cd ..

- name: Upload Artifact
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: BLIS-Standalone
path: BLIS-Standalone.zip

- name: Prepare Update Payload
shell: bash
run: |
mkdir -p BLIS-Update
cp -r ./BLIS/htdocs BLIS-Update/
cp -r ./BLIS/db BLIS-Update/
cp -r ./BLIS/vendor BLIS-Update/
cp -r ./BLIS/local BLIS-Update/
cp ./BLIS/version.json BLIS-Update/
if [ "${{ inputs.include_server_runtime }}" = "true" ]; then
cp -r ./BLISRuntime/server BLIS-Update/
fi
if [ "${{ inputs.include_launcher }}" = "true" ]; then
cp ./BLIS-NG/bin/Release/net10.0/win-x64/publish/BLIS-NG.exe BLIS-Update/
fi

- name: Create Update Zip
shell: bash
run: |
cd BLIS-Update && zip -r ../blis-update.zip . && cd ..

- name: Upload Update Artifact
uses: actions/upload-artifact@v4
with:
name: BLIS-Update
path: blis-update.zip

- name: Push Git Tag
if: ${{ inputs.push_tag == true }}
shell: bash
run: |
TAG="${{ steps.versioning.outputs.tag_name }}"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
git -C BLIS tag "$TAG"
git -C BLIS push origin "$TAG"
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@
/log/*
/local/log*
/local/UILog*
/logs/
# Per-lab language data folders generated at runtime (langdata_{lab_config_id})
/local/langdata_1

# OS generated files #
######################
Expand Down
45 changes: 45 additions & 0 deletions bin/crypto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env php
<?php

require_once(__DIR__."/../htdocs/encryption/encryption.php");

if ($argc < 2) {
echo("You must specify at least \"encrypt\" or \"decrypt\".\n");
die(1);
}

$mode = strtolower($argv[1]);

if ($mode == "encrypt") {
$input = $argv[2];
$output = $argv[3];
$keyfile = $argv[4];

$result = Encryption::encryptFile($input, $output, $keyfile);

if ($result) {
$log->info("Encryption succeeded.");
}
}

if ($mode == "decrypt") {
$input = $argv[2];
$output = $argv[3];
$keyfile = $argv[4];

$result = Encryption::decryptFile($input, $output, $keyfile);

if ($result) {
$log->info("Decryption succeeded.");
}
}

if ($mode == "gen") {
$filename = $argv[2];

$key = sodium_crypto_box_keypair();
file_put_contents($filename, base64_encode($key));

$pubkey = sodium_crypto_box_publickey($key);
file_put_contents($filename . ".pub", base64_encode($pubkey));
}
9 changes: 9 additions & 0 deletions db/migrations/lab/20250915025855_add_keys_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE TABLE IF NOT EXISTS `keys` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`type` varchar(100) NOT NULL,
`data` varchar(100) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ALTER TABLE `lab_config` ADD COLUMN `backup_encryption_enabled` TINYINT(1) NOT NULL DEFAULT 0;

ALTER TABLE `lab_config` ADD COLUMN `backup_encryption_key_id` int(11) unsigned DEFAULT NULL;
27 changes: 13 additions & 14 deletions docker/config/php.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
; BLIS Notes
; Originally from the default PHP 5.6 config from ondrej/php PPA on Ubuntu Focal.
; Updated for PHP 7.4 compatibility.
; The original file comes from the default PHP 5.6 config from ondrej/php PPA on Ubuntu Focal.
; Modifications are made below.

[PHP]
Expand Down Expand Up @@ -206,8 +205,9 @@ engine = On
; http://php.net/short-open-tag
short_open_tag = On

; asp_tags directive was removed in PHP 7.0
; asp_tags = Off
; Allow ASP-style <% %> tags.
; http://php.net/asp-tags
asp_tags = Off

; The number of significant digits displayed in floating point numbers.
; http://php.net/precision
Expand Down Expand Up @@ -293,8 +293,7 @@ unserialize_callback_func =
; When floats & doubles are serialized store serialize_precision significant
; digits after the floating point. The default value ensures that when floats
; are decoded with unserialize, the data will remain the same.
; BLIS modification: changed from 17 to -1 for PHP 7.1+ (ensures float round-trip accuracy)
serialize_precision = -1
serialize_precision = 17

; open_basedir, if set, limits all file operations to the defined directory
; and below. This directive makes most sense if used in a per-directory
Expand Down Expand Up @@ -531,8 +530,8 @@ report_memleaks = On
; Default Value: Off
; Development Value: On
; Production Value: Off
; track_errors was removed in PHP 7.2
; track_errors = Off
; http://php.net/track-errors
track_errors = Off

; Turn off normal error reporting and emit XML-RPC error XML
; http://php.net/xmlrpc-errors
Expand Down Expand Up @@ -1079,8 +1078,8 @@ mail.add_x_header = On
;mail.log = syslog

[SQL]
; sql.safe_mode was removed in PHP 7.2
; sql.safe_mode = Off
; http://php.net/sql.safe-mode
sql.safe_mode = Off

[ODBC]
; http://php.net/odbc.default-db
Expand Down Expand Up @@ -1608,8 +1607,8 @@ session.use_trans_sid = 0
; This option may also be set to the name of any hash function supported by
; the hash extension. A list of available hashes is returned by the hash_algos()
; function.
; session.hash_function was removed in PHP 7.1 (use session.sid_length and session.sid_bits_per_character instead)
; session.hash_function = 0
; http://php.net/session.hash-function
session.hash_function = 0

; Define how many bits are stored in each character when converting
; the binary hash data to something readable.
Expand All @@ -1620,8 +1619,8 @@ session.use_trans_sid = 0
; Default Value: 4
; Development Value: 5
; Production Value: 5
; session.hash_bits_per_character was removed in PHP 7.1 (use session.sid_bits_per_character instead)
; session.hash_bits_per_character = 5
; http://php.net/session.hash-bits-per-character
session.hash_bits_per_character = 5

; The URL rewriter will look for URLs in a defined set of HTML tags.
; form/fieldset are special; if you include them here, the rewriter will
Expand Down
2 changes: 0 additions & 2 deletions htdocs/.htaccess
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,6 @@ RewriteRule ^lab_backups\.php$ export/lab_backups.php
RewriteRule ^export/backups/(.+\.zip)$ export/get_file.php?f=backups/$1
RewriteRule ^export_to_excel\.php$ export/export_to_excel.php
RewriteRule ^export_to_excel_get_test_types\.php$ export/export_to_excel_get_test_types.php
RewriteRule ^export_to_excel_get_custom_patient_fields\.php$ export/export_to_excel_get_custom_patient_fields.php
RewriteRule ^export_to_excel_get_custom_specimen_fields\.php$ export/export_to_excel_get_custom_specimen_fields.php
RewriteRule ^export_excel_dailylog\.php$ export/export_excel_dailylog.php


Expand Down
13 changes: 7 additions & 6 deletions htdocs/Language/lang_update.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
<?php

$local_path = getenv("LOCAL_DIR") ?: realpath(__DIR__."/../../local");

$directories = scandir('../../local');
$directories = scandir($local_path);
foreach($directories as $directory){
if($directory=='.' or $directory=='..' ){
//echo 'dot';
}else{
if (strpos($directory,'test') !== false && is_dir("../../local/".$directory)) {
copy("en.php","../../local/".$directory."/en.php");
copy("default.php","../../local/".$directory."/default.php");
copy("fr.php","../../local/".$directory."/fr.php");
if (strpos($directory,'test') !== false && is_dir($local_path."/".$directory)) {
copy("en.php",$local_path."/".$directory."/en.php");
copy("default.php",$local_path."/".$directory."/default.php");
copy("fr.php",$local_path."/".$directory."/fr.php");
echo $directory .'<br />';
}

}
}

Expand Down
5 changes: 3 additions & 2 deletions htdocs/ajax/billing_update.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
disable_billing();
}

$name="../../logo_billing_".$lab_config_id.".jpg";
$success = move_uploaded_file($_FILES["billingLogo"]["tmp_name"],$name);
$logos_dir = PlatformLib::ensurePath($STORAGE_DIR, 'logos');
$name = $logos_dir . "/logo_billing_" . $lab_config_id . ".jpg";
$success = move_uploaded_file($_FILES["billingLogo"]["tmp_name"], $name);
$a = update_currency_name_in_lab_config_settings($_REQUEST['default_currency']);
$b = update_currency_delimiter_in_lab_config_settings($_REQUEST['currency_delimiter']);
echo $a+$b;
Expand Down
3 changes: 2 additions & 1 deletion htdocs/ajax/report_config_update.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
$ClinicalData = 1;
else
$ClinicalData = 0;
$name="../../logo_".$lab_config_id.".jpg";
$logos_dir = PlatformLib::ensurePath($STORAGE_DIR, 'logos');
$name = $logos_dir . "/logo_" . $lab_config_id . ".jpg";
# Header text
$align_header=array();
$align_header[0]=db_escape($_REQUEST['header']);
Expand Down
Loading
Loading