[med-svn] [Git][med-team/orthanc][master] 6 commits: New upstream version 1.9.2+really1.9.1+dfsg
Sebastien Jodogne (@jodogne-guest)
gitlab at salsa.debian.org
Wed Jul 21 13:02:23 BST 2021
Sebastien Jodogne pushed to branch master at Debian Med / orthanc
Commits:
00cd22e3 by Étienne Mollier at 2021-06-05T13:55:14+02:00
New upstream version 1.9.2+really1.9.1+dfsg
- - - - -
ea7f87df by jodogne-guest at 2021-07-21T12:46:51+02:00
New upstream version 1.9.6+dfsg
- - - - -
dd4b6fc3 by jodogne-guest at 2021-07-21T12:46:53+02:00
Update upstream source from tag 'upstream/1.9.6+dfsg'
Update to upstream version '1.9.6+dfsg'
with Debian dir fc3706a8b8e3c21f0b289e9a6555a7cb83ac3c39
- - - - -
0b8f7fb9 by jodogne-guest at 2021-07-21T12:47:50+02:00
preparing for 1.9.6+dfsg-1
- - - - -
1dea6937 by jodogne-guest at 2021-07-21T13:20:55+02:00
updated configuration files
- - - - -
e4616e85 by jodogne-guest at 2021-07-21T14:01:26+02:00
Upload to experimental
- - - - -
20 changed files:
- .hg_archival.txt
- NEWS
- OrthancFramework/Resources/CMake/DownloadOrthancFramework.cmake
- OrthancFramework/Resources/CMake/OrthancFrameworkParameters.cmake
- OrthancFramework/Sources/Compression/ZipReader.cpp
- OrthancFramework/Sources/Compression/ZipWriter.cpp
- OrthancServer/OrthancExplorer/explorer.html
- OrthancServer/OrthancExplorer/explorer.js
- OrthancServer/OrthancExplorer/query-retrieve.js
- OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h
- OrthancServer/Resources/Configuration.json
- OrthancServer/Resources/Samples/ImportDicomFiles/ImportDicomFiles.py
- OrthancServer/Resources/Samples/ImportDicomFiles/OrthancImport.py
- OrthancServer/Sources/OrthancRestApi/OrthancRestArchive.cpp
- OrthancServer/Sources/ServerContext.cpp
- debian/changelog
- debian/configuration/orthanc.json
- debian/docs/Orthanc.8
- debian/docs/OrthancRecoverCompressedFile.8
- debian/docs/orthanc_upgrade.8
Changes:
=====================================
.hg_archival.txt
=====================================
@@ -1,6 +1,6 @@
repo: 3959d33612ccaadc0d4d707227fbed09ac35e5fe
-node: c26a87e0fed76dba1882e9310fad333b4c185fb0
-branch: Orthanc-1.9.5
+node: b1319a5304fb494e567e32dc53aa11a6978eb554
+branch: Orthanc-1.9.6
latesttag: toa2020012703
-latesttagdistance: 917
-changessincelatesttag: 1081
+latesttagdistance: 928
+changessincelatesttag: 1093
=====================================
NEWS
=====================================
@@ -2,6 +2,21 @@ Pending changes in the mainline
===============================
+Version 1.9.6 (2021-07-21)
+==========================
+
+Orthanc Explorer
+----------------
+
+* In lookup and query/retrieve, possibility to provide a specific study date
+* Clicking on "Send to remote modality" displays the job information to monitor progress
+
+Maintenance
+-----------
+
+* Fix orphaned attachments if bad revision number is provided
+
+
Version 1.9.5 (2021-07-08)
==========================
=====================================
OrthancFramework/Resources/CMake/DownloadOrthancFramework.cmake
=====================================
@@ -132,6 +132,8 @@ if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" OR
set(ORTHANC_FRAMEWORK_MD5 "9b86e6f00e03278293cd15643cc0233f")
elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.9.4")
set(ORTHANC_FRAMEWORK_MD5 "6d5ca4a73ac7d42445041ca79de1624d")
+ elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.9.5")
+ set(ORTHANC_FRAMEWORK_MD5 "10fc64de1254a095e5d3ed3931f0cfbb")
# Below this point are development snapshots that were used to
# release some plugin, before an official release of the Orthanc
=====================================
OrthancFramework/Resources/CMake/OrthancFrameworkParameters.cmake
=====================================
@@ -23,7 +23,7 @@
#####################################################################
# Version of the build, should always be "mainline" except in release branches
-set(ORTHANC_VERSION "1.9.5")
+set(ORTHANC_VERSION "1.9.6")
# Version of the database schema. History:
# * Orthanc 0.1.0 -> Orthanc 0.3.0 = no versioning
=====================================
OrthancFramework/Sources/Compression/ZipReader.cpp
=====================================
@@ -38,7 +38,7 @@
/**
* I have not been able to correctly define "ssize_t" on all versions
- * of Visual Studio. As a consequence, I prefered to switch "ssize_t"
+ * of Visual Studio. As a consequence, I preferred to switch "ssize_t"
* to "SSIZE_T", that is properly defined on both MSVC 2008 and 2015.
* I define the macro "SSIZE_T" as an alias to "ssize_t" on
* POSIX-compliant platforms that wouldn't have "SSIZE_T" defined.
=====================================
OrthancFramework/Sources/Compression/ZipWriter.cpp
=====================================
@@ -452,7 +452,7 @@ namespace Orthanc
}
catch (OrthancException& e) // Don't throw exceptions in destructors
{
- LOG(ERROR) << "Catched exception in destructor: " << e.What();
+ LOG(ERROR) << "Caught exception in destructor: " << e.What();
}
}
=====================================
OrthancServer/OrthancExplorer/explorer.html
=====================================
@@ -87,6 +87,11 @@
</select>
</div>
+ <div data-role="fieldcontain">
+ <label for="lookup-study-date-specific"></label>
+ <input type="date" name="lookup-study-date-specific" id="lookup-study-date-specific" />
+ </div>
+
<fieldset class="ui-grid-b">
<div class="ui-block-a">
<a href="#find-patients" data-role="button" data-theme="b" data-direction="reverse">All patients</a>
@@ -494,7 +499,7 @@
<div data-role="fieldcontain">
<label for="qr-value">Value for this field:</label>
- <input type="text" name="qr-value" id="qr-value" value="*" />
+ <input type="text" name="qr-value" id="qr-value" value="" />
</div>
<div data-role="fieldcontain">
@@ -503,6 +508,11 @@
</select>
</div>
+ <div data-role="fieldcontain">
+ <label for="qr-date-specific"></label>
+ <input type="date" name="qr-date-specific" id="qr-date-specific" />
+ </div>
+
<div data-role="fieldcontain" id="qr-modalities">
<div data-role="fieldcontain">
<fieldset data-role="controlgroup" data-type="horizontal">
=====================================
OrthancServer/OrthancExplorer/explorer.js
=====================================
@@ -506,23 +506,39 @@ $('#lookup').live('pagebeforeshow', function() {
target.append($('<option>').attr('value', GenerateDicomDate(-31) + '-').text('Last 31 days'));
target.append($('<option>').attr('value', GenerateDicomDate(-31 * 3) + '-').text('Last 3 months'));
target.append($('<option>').attr('value', GenerateDicomDate(-365) + '-').text('Last year'));
+ target.append($('<option>').attr('value', 'specific').text('Specific date'));
target.selectmenu('refresh');
$('#lookup-result').hide();
+ $('#lookup-study-date-specific').hide();
+});
+
+
+$('#lookup-study-date').live('change', function() {
+ if ($(this).val() == 'specific') {
+ $('#lookup-study-date-specific').show();
+ } else {
+ $('#lookup-study-date-specific').hide();
+ }
});
$('#lookup-submit').live('click', function() {
- var lookup;
+ var lookup, studyDate;
$('#lookup-result').hide();
+ studyDate = $('#lookup-study-date').val();
+ if (studyDate == 'specific') {
+ studyDate = IsoToDicomDate($('#lookup-study-date-specific').val());
+ }
+
lookup = {
'Level' : 'Study',
'Expand' : true,
'Limit' : LIMIT_RESOURCES + 1,
'Query' : {
- 'StudyDate' : $('#lookup-study-date').val()
+ 'StudyDate' : studyDate
},
'Full' : true
};
@@ -541,6 +557,9 @@ $('#lookup-submit').live('click', function() {
else if (input.id == 'lookup-study-description') {
lookup['Query']['StudyDescription'] = input.value;
}
+ else if (input.id == 'lookup-study-date-specific') {
+ // Ignore
+ }
else {
console.error('Unknown lookup field: ' + input.id);
}
@@ -1260,19 +1279,23 @@ $('#instance-store,#series-store,#study-store,#patient-store').live('click', fun
}
if (url != '') {
+ /**
+ * In Orthanc <= 1.9.5, synchronous job was used, which caused a
+ * non-intuitive behavior because of AJAX timeouts on large
+ * studies. We now use an asynchronous call.
+ * https://groups.google.com/g/orthanc-users/c/r2LoAp72AWI/m/cVaFXopUBAAJ
+ **/
$.ajax({
url: url,
type: 'POST',
- dataType: 'text',
- data: pageData.uuid,
- async: true, // Necessary to block UI
- beforeSend: function() {
- $.blockUI({ message: $(loading) });
- },
- complete: function(s) {
- $.unblockUI();
- },
- success: function(s) {
+ data: JSON.stringify({
+ 'Synchronous' : false,
+ 'Resources' : [ pageData.uuid ]
+ }),
+ dataType: 'json',
+ async: false,
+ success: function(job) {
+ window.location.assign('explorer.html#job?uuid=' + job.ID);
},
error: function() {
alert('Error during store');
=====================================
OrthancServer/OrthancExplorer/query-retrieve.js
=====================================
@@ -31,6 +31,11 @@
**/
+function IsoToDicomDate(s)
+{
+ return s.substring(0, 4) + s.substring(5, 7) + s.substring(8, 10);
+}
+
function GenerateDicomDate(days)
{
var today = new Date();
@@ -48,8 +53,7 @@ function GenerateDicomDate(days)
var timezoneOffset = today.getTimezoneOffset() * 60 * 1000;
var localDate = new Date(utc.getTime() - timezoneOffset);
- var s = localDate.toISOString();
- return s.substring(0, 4) + s.substring(5, 7) + s.substring(8, 10);
+ return IsoToDicomDate(localDate.toISOString());
}
@@ -85,7 +89,19 @@ $('#query-retrieve').live('pagebeforeshow', function() {
targetDate.append($('<option>').attr('value', GenerateDicomDate(-31) + '-').text('Last 31 days'));
targetDate.append($('<option>').attr('value', GenerateDicomDate(-31 * 3) + '-').text('Last 3 months'));
targetDate.append($('<option>').attr('value', GenerateDicomDate(-365) + '-').text('Last year'));
+ targetDate.append($('<option>').attr('value', 'specific').text('Specific date'));
targetDate.selectmenu('refresh');
+
+ $('#qr-date-specific').hide();
+});
+
+
+$('#qr-date').live('change', function() {
+ if ($(this).val() == 'specific') {
+ $('#qr-date-specific').show();
+ } else {
+ $('#qr-date-specific').hide();
+ }
});
@@ -120,7 +136,12 @@ $('#qr-echo').live('click', function() {
$('#qr-submit').live('click', function() {
- var query, server, modalities, field;
+ var query, server, modalities, field, studyDate;
+
+ studyDate = $('#qr-date').val();
+ if (studyDate == 'specific') {
+ studyDate = IsoToDicomDate($('#qr-date-specific').val());
+ }
query = {
'Level' : 'Study',
@@ -130,7 +151,7 @@ $('#qr-submit').live('click', function() {
'PatientID' : '',
'PatientName' : '',
'PatientSex' : '',
- 'StudyDate' : $('#qr-date').val(),
+ 'StudyDate' : studyDate,
'StudyDescription' : ''
}
};
=====================================
OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h
=====================================
@@ -7501,9 +7501,9 @@ extern "C"
* @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
* @param pathRegularExpression Regular expression for the URI. May contain groups.
* @param getHandler The callback function to handle REST calls using the GET HTTP method.
- * @param postHandler The callback function to handle REST calls using the GET POST method.
- * @param deleteHandler The callback function to handle REST calls using the GET DELETE method.
- * @param putHandler The callback function to handle REST calls using the GET PUT method.
+ * @param postHandler The callback function to handle REST calls using the POST HTTP method.
+ * @param deleteHandler The callback function to handle REST calls using the DELETE HTTP method.
+ * @param putHandler The callback function to handle REST calls using the PUT HTTP method.
* @param addChunk The callback invoked when a new chunk is available for the request body of a POST or PUT call.
* @param execute The callback invoked once the entire body of a POST or PUT call is read.
* @param finalize The callback invoked to release the resources associated with a POST or PUT call.
=====================================
OrthancServer/Resources/Configuration.json
=====================================
@@ -680,7 +680,8 @@
"MediaArchiveSize" : 1,
// Performance setting to specify how Orthanc accesses the storage
- // area during C-FIND. Three modes are available: (1) "Always"
+ // area during find operations (C-FIND, /tools/find API route and
+ // QIDO-RS in dicom-web). Three modes are available: (1) "Always"
// allows Orthanc to read the storage area as soon as it needs an
// information that is not present in its database (slowest mode),
// (2) "Never" prevents Orthanc from accessing the storage area, and
@@ -797,7 +798,7 @@
// identifier is only useful in the case of multiple
// readers/writers, in order to avoid collisions between multiple
// Orthanc servers. If unset, this identifier is taken as a SHA-1
- // hash derived from the MAC adddresses of the network interfaces,
+ // hash derived from the MAC addresses of the network interfaces,
// and from the AET and TCP ports used by Orthanc. Manually setting
// this option is needed in Docker/Kubernetes environments. (new in
// Orthanc 1.9.2)
=====================================
OrthancServer/Resources/Samples/ImportDicomFiles/ImportDicomFiles.py
=====================================
@@ -19,11 +19,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import base64
+import httplib2
+import json
import os
-import sys
import os.path
-import httplib2
-import base64
+import sys
if len(sys.argv) != 4 and len(sys.argv) != 6:
print("""
@@ -40,23 +41,42 @@ For instance: %s 127.0.0.1 8042 .
URL = 'http://%s:%d/instances' % (sys.argv[1], int(sys.argv[2]))
-success_count = 0
+dicom_count = 0
+json_count = 0
total_file_count = 0
+def IsJson(content):
+ try:
+ if (sys.version_info >= (3, 0)):
+ json.loads(content.decode())
+ return True
+ else:
+ json.loads(content)
+ return True
+ except:
+ return False
+
+
# This function will upload a single file to Orthanc through the REST API
def UploadFile(path):
- global success_count
+ global dicom_count
+ global json_count
global total_file_count
- f = open(path, "rb")
+ f = open(path, 'rb')
content = f.read()
f.close()
total_file_count += 1
- try:
- sys.stdout.write("Importing %s" % path)
+ sys.stdout.write('Importing %s' % path)
+
+ if IsJson(content):
+ sys.stdout.write(' => ignored JSON file\n')
+ json_count += 1
+ return
+ try:
h = httplib2.Http()
headers = { 'content-type' : 'application/dicom' }
@@ -73,24 +93,24 @@ def UploadFile(path):
# not always work)
# http://en.wikipedia.org/wiki/Basic_access_authentication
creds_str = username + ':' + password
- creds_str_bytes = creds_str.encode("ascii")
+ creds_str_bytes = creds_str.encode('ascii')
creds_str_bytes_b64 = b'Basic ' + base64.b64encode(creds_str_bytes)
- headers['authorization'] = creds_str_bytes_b64.decode("ascii")
+ headers['authorization'] = creds_str_bytes_b64.decode('ascii')
resp, content = h.request(URL, 'POST',
body = content,
headers = headers)
if resp.status == 200:
- sys.stdout.write(" => success\n")
- success_count += 1
+ sys.stdout.write(' => success\n')
+ dicom_count += 1
else:
- sys.stdout.write(" => failure (Is it a DICOM file? Is there a password?)\n")
+ sys.stdout.write(' => failure (Is it a DICOM file? Is there a password?)\n')
except:
type, value, traceback = sys.exc_info()
sys.stderr.write(str(value))
- sys.stdout.write(" => unable to connect (Is Orthanc running? Is there a password?)\n")
+ sys.stdout.write(' => unable to connect (Is Orthanc running? Is there a password?)\n')
if os.path.isfile(sys.argv[3]):
@@ -102,7 +122,13 @@ else:
for f in files:
UploadFile(os.path.join(root, f))
-if success_count == total_file_count:
- print("\nSummary: all %d DICOM file(s) have been imported successfully" % success_count)
+
+if dicom_count + json_count == total_file_count:
+ print('\nSUCCESS: %d DICOM file(s) have been successfully imported' % dicom_count)
else:
- print("\nSummary: %d out of %d files have been imported successfully as DICOM instances" % (success_count, total_file_count))
+ print('\nWARNING: Only %d out of %d file(s) have been successfully imported as DICOM instance(s)' % (dicom_count, total_file_count - json_count))
+
+if json_count != 0:
+ print('NB: %d JSON file(s) have been ignored' % json_count)
+
+print('')
=====================================
OrthancServer/Resources/Samples/ImportDicomFiles/OrthancImport.py
=====================================
@@ -22,6 +22,7 @@
import argparse
import bz2
import gzip
+import json
import os
import requests
import sys
@@ -71,12 +72,31 @@ Are you sure ["yes" to go on]?""" % args.server)
IMPORTED_STUDIES = set()
COUNT_ERROR = 0
-COUNT_SUCCESS = 0
-
+COUNT_DICOM = 0
+COUNT_JSON = 0
+
+
+def IsJson(content):
+ try:
+ if (sys.version_info >= (3, 0)):
+ json.loads(content.decode())
+ return True
+ else:
+ json.loads(content)
+ return True
+ except:
+ return False
+
+
def UploadBuffer(dicom):
global IMPORTED_STUDIES
global COUNT_ERROR
- global COUNT_SUCCESS
+ global COUNT_DICOM
+ global COUNT_JSON
+
+ if IsJson(dicom):
+ COUNT_JSON += 1
+ return
auth = HTTPBasicAuth(args.username, args.password)
r = requests.post('%s/instances' % args.url, auth = auth, data = dicom)
@@ -93,7 +113,7 @@ def UploadBuffer(dicom):
raise
info = r.json()
- COUNT_SUCCESS += 1
+ COUNT_DICOM += 1
if not info['ParentStudy'] in IMPORTED_STUDIES:
IMPORTED_STUDIES.add(info['ParentStudy'])
@@ -219,8 +239,14 @@ for path in args.files:
print('')
-print('Status:')
-print(' %d DICOM instances properly imported' % COUNT_SUCCESS)
+
+if COUNT_ERROR == 0:
+ print('SUCCESS:')
+else:
+ print('WARNING:')
+
+print(' %d DICOM instances properly imported' % COUNT_DICOM)
print(' %d DICOM studies properly imported' % len(IMPORTED_STUDIES))
+print(' %d JSON files ignored' % COUNT_JSON)
print(' Error in %d files' % COUNT_ERROR)
print('')
=====================================
OrthancServer/Sources/OrthancRestApi/OrthancRestArchive.cpp
=====================================
@@ -502,7 +502,7 @@ namespace Orthanc
.SetRequestField("Synchronous", RestApiCallDocumentation::Type_Boolean,
"If `true`, create the archive in synchronous mode, which means that the HTTP answer will directly "
"contain the ZIP file. This is the default, easy behavior. However, if global configuration option "
- "\"SynchronousZipStream\" is set to \"false\", asynchronous transfers should be prefered for "
+ "\"SynchronousZipStream\" is set to \"false\", asynchronous transfers should be preferred for "
"large amount of data, as the creation of the temporary file might lead to network timeouts.", false)
.SetRequestField("Asynchronous", RestApiCallDocumentation::Type_Boolean,
"If `true`, create the archive in asynchronous mode, which means that a job is submitted to create "
=====================================
OrthancServer/Sources/ServerContext.cpp
=====================================
@@ -1174,16 +1174,25 @@ namespace Orthanc
StorageAccessor accessor(area_, GetMetricsRegistry());
FileInfo attachment = accessor.Write(data, size, attachmentType, compression, storeMD5_);
- StoreStatus status = index_.AddAttachment(
- newRevision, attachment, resourceId, hasOldRevision, oldRevision, oldMD5);
- if (status != StoreStatus_Success)
+ try
{
- accessor.Remove(attachment);
- return false;
+ StoreStatus status = index_.AddAttachment(
+ newRevision, attachment, resourceId, hasOldRevision, oldRevision, oldMD5);
+ if (status != StoreStatus_Success)
+ {
+ accessor.Remove(attachment);
+ return false;
+ }
+ else
+ {
+ return true;
+ }
}
- else
+ catch (OrthancException&)
{
- return true;
+ // Fixed in Orthanc 1.9.6
+ accessor.Remove(attachment);
+ throw;
}
}
=====================================
debian/changelog
=====================================
@@ -1,3 +1,9 @@
+orthanc (1.9.6+dfsg-1) experimental; urgency=medium
+
+ * New upstream version
+
+ -- Sebastien Jodogne <s.jodogne at gmail.com> Wed, 21 Jul 2021 12:47:01 +0200
+
orthanc (1.9.5+dfsg-1) experimental; urgency=medium
* New upstream version
=====================================
debian/configuration/orthanc.json
=====================================
@@ -675,7 +675,8 @@
"MediaArchiveSize" : 1,
// Performance setting to specify how Orthanc accesses the storage
- // area during C-FIND. Three modes are available: (1) "Always"
+ // area during find operations (C-FIND, /tools/find API route and
+ // QIDO-RS in dicom-web). Three modes are available: (1) "Always"
// allows Orthanc to read the storage area as soon as it needs an
// information that is not present in its database (slowest mode),
// (2) "Never" prevents Orthanc from accessing the storage area, and
@@ -792,7 +793,7 @@
// identifier is only useful in the case of multiple
// readers/writers, in order to avoid collisions between multiple
// Orthanc servers. If unset, this identifier is taken as a SHA-1
- // hash derived from the MAC adddresses of the network interfaces,
+ // hash derived from the MAC addresses of the network interfaces,
// and from the AET and TCP ports used by Orthanc. Manually setting
// this option is needed in Docker/Kubernetes environments. (new in
// Orthanc 1.9.2)
=====================================
debian/docs/Orthanc.8
=====================================
@@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.3.
-.TH ORTHANC "8" "July 2021" "Orthanc 1.9.5" "System Administration Utilities"
+.TH ORTHANC "8" "July 2021" "Orthanc 1.9.6" "System Administration Utilities"
.SH NAME
Orthanc \- Lightweight, RESTful DICOM server for healthcare and medical research
.SH SYNOPSIS
=====================================
debian/docs/OrthancRecoverCompressedFile.8
=====================================
@@ -1,4 +1,4 @@
-.TH ORTHANC "8" "July 2021" "Orthanc 1.9.5" "System Administration tools and Deamons"
+.TH ORTHANC "8" "July 2021" "Orthanc 1.9.6" "System Administration tools and Deamons"
.SH NAME
Orthanc \- Lightweight, RESTful DICOM server for healthcare and medical research
.SH SYNOPSIS
=====================================
debian/docs/orthanc_upgrade.8
=====================================
@@ -1,4 +1,4 @@
-.TH ORTHANC "8" "July 2021" "Orthanc 1.9.5" "System Administration tools and Deamons"
+.TH ORTHANC "8" "July 2021" "Orthanc 1.9.6" "System Administration tools and Deamons"
.SH NAME
Orthanc \- Lightweight, RESTful DICOM server for healthcare and medical research
.SH SYNOPSIS
View it on GitLab: https://salsa.debian.org/med-team/orthanc/-/compare/7f319de1c7e09c00c77e339b6ec9c71423a9a712...e4616e85d43829f8a029df36154bde160cdd31ee
--
View it on GitLab: https://salsa.debian.org/med-team/orthanc/-/compare/7f319de1c7e09c00c77e339b6ec9c71423a9a712...e4616e85d43829f8a029df36154bde160cdd31ee
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20210721/6d7b78dc/attachment-0001.htm>
More information about the debian-med-commit
mailing list