From 024cfc3f2004f069d302424817a3d682b028507e Mon Sep 17 00:00:00 2001
From: Robert Sparks <rjsparks@nostrum.com>
Date: Fri, 3 Dec 2021 18:15:48 +0000
Subject: [PATCH] Provide a more direct replacement for tools.ietf.org/id at
 doc/id. Commit ready for merge.  - Legacy-Id: 19747

---
 ietf/doc/tests.py     | 52 +++++++++++++++++++++++++++++++++++++++++++
 ietf/doc/urls.py      |  7 ++++++
 ietf/doc/views_doc.py | 37 ++++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+)

diff --git a/ietf/doc/tests.py b/ietf/doc/tests.py
index 98e69329e..d630a90c3 100644
--- a/ietf/doc/tests.py
+++ b/ietf/doc/tests.py
@@ -2682,3 +2682,55 @@ class RfcdiffSupportTests(TestCase):
         # tricky draft names
         self.do_rfc_with_broken_history_test(draft_name='draft-gizmo-01')
         self.do_rfc_with_broken_history_test(draft_name='draft-oh-boy-what-a-draft-02-03')
+
+class RawIdTests(TestCase):
+
+    def __init__(self, *args, **kwargs):
+        self.view = "ietf.doc.views_doc.document_raw_id"
+        self.mimetypes = {'txt':'text/plain','html':'text/html','xml':'application/xml'}
+        super(self.__class__, self).__init__(*args, **kwargs)
+
+    def should_succeed(self, argdict):
+        url = urlreverse(self.view, kwargs=argdict)
+        r = self.client.get(url)
+        self.assertEqual(r.status_code,200)
+        self.assertEqual(r.get('Content-Type'),f"{self.mimetypes[argdict.get('ext','txt')]};charset=utf-8")
+
+    def should_404(self, argdict):
+        url = urlreverse(self.view, kwargs=argdict)
+        r = self.client.get(url)
+        self.assertEqual(r.status_code, 404)
+
+    def test_raw_id(self):
+        draft = WgDraftFactory(create_revisions=range(0,2))
+
+        dir = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
+        for r in range(0,2):
+            rev = f'{r:02d}'
+            (Path(dir) / f'{draft.name}-{rev}.txt').touch()
+            if r == 1:
+                (Path(dir) / f'{draft.name}-{rev}.html').touch()
+                (Path(dir) / f'{draft.name}-{rev}.xml').touch()
+
+        self.should_succeed(dict(name=draft.name))
+        for ext in ('txt', 'html', 'xml'):
+            self.should_succeed(dict(name=draft.name, ext=ext))
+            self.should_succeed(dict(name=draft.name, rev='01', ext=ext))
+        self.should_404(dict(name=draft.name, ext='pdf'))
+
+        self.should_succeed(dict(name=draft.name, rev='00'))
+        self.should_succeed(dict(name=draft.name, rev='00',ext='txt'))
+        self.should_404(dict(name=draft.name, rev='00',ext='html'))
+
+    def test_raw_id_rfc(self):
+        rfc = WgRfcFactory()
+        dir = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
+        (Path(dir) / f'{rfc.name}-{rfc.rev}.txt').touch()
+        self.should_succeed(dict(name=rfc.name))
+        self.should_404(dict(name=rfc.canonical_name()))
+
+    def test_non_draft(self):
+        charter = CharterFactory()
+        self.should_404(dict(name=charter.name))
+
+
diff --git a/ietf/doc/urls.py b/ietf/doc/urls.py
index ceb2ff216..47a8f5a03 100644
--- a/ietf/doc/urls.py
+++ b/ietf/doc/urls.py
@@ -65,9 +65,16 @@ urlpatterns = [
     url(r'^stats/newrevisiondocevent/data/?$', views_stats.chart_data_newrevisiondocevent),
     url(r'^stats/person/(?P<id>[0-9]+)/drafts/conf/?$', views_stats.chart_conf_person_drafts),
     url(r'^stats/person/(?P<id>[0-9]+)/drafts/data/?$', views_stats.chart_data_person_drafts),
+
+# This block should really all be at the idealized docs.ietf.org service
     url(r'^html/(?P<name>bcp[0-9]+?)(\.txt|\.html)?/?$', RedirectView.as_view(url=settings.RFC_EDITOR_INFO_BASE_URL+"%(name)s", permanent=False)), 
     url(r'^html/(?P<name>std[0-9]+?)(\.txt|\.html)?/?$', RedirectView.as_view(url=settings.RFC_EDITOR_INFO_BASE_URL+"%(name)s", permanent=False)), 
     url(r'^html/%(name)s(?:-%(rev)s)?(\.txt|\.html)?/?$' % settings.URL_REGEXPS, views_doc.document_html),
+
+    url(r'^id/%(name)s(?:-%(rev)s)?(?:\.(?P<ext>(txt|html|xml)))?/?$' % settings.URL_REGEXPS, views_doc.document_raw_id),
+
+# End of block that should be an idealized docs.ietf.org service instead
+
     url(r'^html/(?P<name>[Rr][Ff][Cc] [0-9]+?)(\.txt|\.html)?/?$', views_doc.document_html),
     url(r'^idnits2-rfcs-obsoleted/?$', views_doc.idnits2_rfcs_obsoleted),
     url(r'^idnits2-rfc-status/?$', views_doc.idnits2_rfc_status),
diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py
index f2ccb3ec9..f73b3de12 100644
--- a/ietf/doc/views_doc.py
+++ b/ietf/doc/views_doc.py
@@ -719,6 +719,43 @@ def document_main(request, name, rev=None):
 
     raise Http404("Document not found: %s" % (name + ("-%s"%rev if rev else "")))
 
+def document_raw_id(request, name, rev=None, ext=None):
+    if not name.startswith('draft-'):
+        raise Http404
+    found = fuzzy_find_documents(name, rev)
+    num_found = found.documents.count()
+    if num_found == 0:
+        raise Http404("Document not found: %s" % name)
+    if num_found > 1:
+        raise Http404("Multiple documents matched: %s" % name)
+
+    doc = found.documents.get()
+
+    if found.matched_rev or found.matched_name.startswith('rfc'):
+        rev = found.matched_rev
+    else:
+        rev = doc.rev
+    if rev:
+        doc = doc.history_set.filter(rev=rev).first() or doc.fake_history_obj(rev)
+
+    base_path = os.path.join(settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR, doc.name + "-" + doc.rev + ".")
+    possible_types = settings.IDSUBMIT_FILE_TYPES
+    found_types=dict()
+    for t in possible_types:
+        if os.path.exists(base_path + t):
+            found_types[t]=base_path+t
+    if ext == None:
+        ext = 'txt'
+    if not ext in found_types:
+        raise Http404('dont have the file for that extension')
+    mimetypes = {'txt':'text/plain','html':'text/html','xml':'application/xml'}
+    try:    
+        with open(found_types[ext],'rb') as f:
+            blob = f.read()
+            return HttpResponse(blob,content_type=f'{mimetypes[ext]};charset=utf-8')
+    except:
+        raise Http404
+
 
 def document_html(request, name, rev=None):
     found = fuzzy_find_documents(name, rev)