[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