Repository: pydicom/pynetdicom

Issue:
Add switch for valieate_ae_title in C-MOVE request
**Is your feature request related to a problem? Please describe.**

I've met a custom DICOM server that allows me to send receiver AE title in C-MOVE request in format "ae_title@IP:port" where ae_title is regular title and IP and port is an address of receiver. It allows them to process C-MOVE requests without maintaining a table of AEs and their addresses.

Of course such AE title is longer than 16 bytes allowed by DICOM standard and I can't use this library without patching.

**Describe the solution you'd like**

I've already made a simplest patch that allows me to switch off the AE title length check in C-MOVE request. Now I'd like to merge it into the main repo to not to maintain a fork.

Now it works only for C-MOVE request so I probably need to make it more general.

**Describe alternatives you've considered**

Now I have to fork the project and maintain it.
I also considered monkey patching but it seems too weird.

**Additional context**

I understand that it's just a non-standard DICOM server and in general project doesn't have to support such things. That's why I ask you to add switch that will just allow users that have such problem to switch off this particular check.

Comments:

Patch:
diff --git a/docs/changelog/v2.0.0.rst b/docs/changelog/v2.0.0.rst
index 15c78b248..ee46b8351 100644
--- a/docs/changelog/v2.0.0.rst
+++ b/docs/changelog/v2.0.0.rst
@@ -4,6 +4,12 @@
 =====
 
 
+Enhancements
+............
+
+* Added configuration option :attr:`_config.ALLOW_LONG_DIMSE_AET` to allow
+  bypassing the length check for elements with a VR of **AE** (:issue:`515`)
+
 Changes
 .......
 
diff --git a/docs/reference/config.rst b/docs/reference/config.rst
index d1676bd2b..fa9e28c0d 100644
--- a/docs/reference/config.rst
+++ b/docs/reference/config.rst
@@ -13,5 +13,6 @@ Configuration Options (:mod:`pynetdicom._config`)
    ENFORCE_UID_CONFORMANCE
    LOG_HANDLER_LEVEL
    USE_SHORT_DIMSE_AET
+   ALLOW_LONG_DIMSE_AET
    LOG_REQUEST_IDENTIFIERS
    LOG_RESPONSE_IDENTIFIERS
diff --git a/pynetdicom/_config.py b/pynetdicom/_config.py
index f8fc47958..f07625023 100644
--- a/pynetdicom/_config.py
+++ b/pynetdicom/_config.py
@@ -52,6 +52,23 @@ Examples
 """
 
 
+ALLOW_LONG_DIMSE_AET = False
+"""Allow the use of non-conformant AE titles.
+
+.. versionadded:: 2.0
+
+If ``False`` then elements with a VR of AE in DIMSE messages will have their
+length checked to ensure conformance, otherwise no length check will be
+performed.
+
+Examples
+--------
+
+>>> from pynetdicom import _config
+>>> _config.ALL_LONG_AET = True
+"""
+
+
 LOG_RESPONSE_IDENTIFIERS = True
 """Log incoming C-FIND, C-GET and C-MOVE response *Identifier* datasets.
 
diff --git a/pynetdicom/apps/qrscp/handlers.py b/pynetdicom/apps/qrscp/handlers.py
index 05d946d78..449314b39 100644
--- a/pynetdicom/apps/qrscp/handlers.py
+++ b/pynetdicom/apps/qrscp/handlers.py
@@ -172,7 +172,7 @@ def handle_get(event, db_path, cli_config, logger):
         try:
             ds = dcmread(match.filename)
         except Exception as exc:
-            logger.error(f"Error reading file: {fpath}")
+            logger.error(f"Error reading file: {match.filename}")
             logger.exception(exc)
             yield 0xC421, None
 
@@ -264,7 +264,7 @@ def handle_move(event, destinations, db_path, cli_config, logger):
         try:
             ds = dcmread(match.filename)
         except Exception as exc:
-            logger.error(f"Error reading file: {fpath}")
+            logger.error(f"Error reading file: {match.filename}")
             logger.exception(exc)
             yield 0xC521, None
 
diff --git a/pynetdicom/utils.py b/pynetdicom/utils.py
index c12df7fa5..239b3532f 100644
--- a/pynetdicom/utils.py
+++ b/pynetdicom/utils.py
@@ -127,8 +127,10 @@ def validate_ae_title(ae_title, use_short=False):
             "AE titles are not allowed to consist entirely of only spaces"
         )
 
-    # Truncate if longer than 16 characters
-    ae_title = ae_title[:16]
+    if not _config.ALLOW_LONG_DIMSE_AET:
+        # Truncate if longer than 16 characters
+        ae_title = ae_title[:16]
+
     if not use_short:
         # Pad out to 16 characters using spaces
         ae_title = ae_title.ljust(16)


Test patch:
diff --git a/pynetdicom/tests/test_utils.py b/pynetdicom/tests/test_utils.py
index da278865b..f697f1b0b 100644
--- a/pynetdicom/tests/test_utils.py
+++ b/pynetdicom/tests/test_utils.py
@@ -97,6 +97,15 @@ class TestValidateAETitle(object):
         with pytest.raises((TypeError, ValueError)):
             validate_ae_title(aet)
 
+    def test_length_check(self):
+        """Test validate_ae_title with no length check."""
+        assert _config.ALLOW_LONG_DIMSE_AET is False
+        aet = b"12345678901234567890"
+        assert 16 == len(validate_ae_title(aet))
+        _config.ALLOW_LONG_DIMSE_AET = True
+        assert 20 == len(validate_ae_title(aet))
+        _config.ALLOW_LONG_DIMSE_AET = False
+
 
 REFERENCE_UID = [
     # UID, (enforced, non-enforced conformance)