diff --git a/ietf/doc/models.py b/ietf/doc/models.py
index cfc153942..34031a65f 100644
--- a/ietf/doc/models.py
+++ b/ietf/doc/models.py
@@ -225,7 +225,10 @@ class DocumentInfo(models.Model):
             else:
                 info = dict(doc=self)
 
-            self._cached_href = format.format(**info)
+            href = format.format(**info)
+            if href.startswith('/'):
+                href = settings.IDTRACKER_BASE_URL + href
+            self._cached_href = href
         return self._cached_href
 
     def set_state(self, state):
@@ -346,13 +349,9 @@ class DocumentInfo(models.Model):
         return e != None and (e.text != "")
 
     def meeting_related(self):
-        answer = False
         if self.type_id in ("agenda","minutes","bluesheets","slides","recording"):
-            answer =  (self.name.split("-")[1] == "interim"
-                       or (self if isinstance(self, Document) else self.doc).session_set.exists())
-            if self.type_id in ("slides",):
-                answer =  answer and self.get_state_slug('reuse_policy')=='single'
-        return answer
+             return self.type_id != "slides" or self.get_state_slug('reuse_policy')=='single'
+        return False
 
     def relations_that(self, relationship):
         """Return the related-document objects that describe a given relationship targeting self."""
@@ -554,20 +553,15 @@ class Document(DocumentInfo):
         name = self.name
         if self.type_id == "draft" and self.get_state_slug() == "rfc":
             name = self.canonical_name()
-        elif self.type_id in ('slides','agenda','minutes','bluesheets','recording'):
+        elif self.type_id in ('slides','bluesheets','recording'):
             session = self.session_set.first()
             if session:
                 meeting = session.meeting
                 if self.type_id == 'recording':
                     url = self.external_url
                 else:
-                    if self.type_id == 'agenda':
-                        url = urlreverse('ietf.meeting.views.session_agenda', kwargs={'num':meeting.number, 'session':session.group.acronym})
-                    elif self.type_id == 'minutes':
-                        url = urlreverse('ietf.meeting.views.session_minutes', kwargs={'num':meeting.number, 'session':session.group.acronym})
-                    else:
-                        filename = self.external_url
-                        url = '%sproceedings/%s/%s/%s' % (settings.IETF_HOST_URL,meeting.number,self.type_id,filename)
+                    filename = self.external_url
+                    url = '%sproceedings/%s/%s/%s' % (settings.IETF_HOST_URL,meeting.number,self.type_id,filename)
                 return url
         return urlreverse('ietf.doc.views_doc.document_main', kwargs={ 'name': name }, urlconf="ietf.urls")
 
diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py
index a7d340df4..7648dc7d7 100644
--- a/ietf/meeting/tests_views.py
+++ b/ietf/meeting/tests_views.py
@@ -72,7 +72,7 @@ class MeetingTests(TestCase):
                                   "This is a slideshow")
         
 
-    def test_agenda(self):
+    def test_meeting_agenda(self):
         meeting = make_meeting_test_data()
         session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
         slot = TimeSlot.objects.get(sessionassignments__session=session,sessionassignments__schedule=meeting.agenda)
@@ -171,8 +171,8 @@ class MeetingTests(TestCase):
         self.assertTrue("BEGIN:VTIMEZONE" in agenda_content)
         self.assertTrue("END:VTIMEZONE" in agenda_content)        
 
-        self.assertTrue(session.agenda().get_absolute_url() in unicontent(r))
-        self.assertTrue(session.materials.filter(type='slides').exclude(states__type__slug='slides',states__slug='deleted').first().get_absolute_url() in unicontent(r))
+        self.assertTrue(session.agenda().href() in unicontent(r))
+        self.assertTrue(session.materials.filter(type='slides').exclude(states__type__slug='slides',states__slug='deleted').first().href() in unicontent(r))
         # TODO - the ics view uses .all on a queryset in a view so it's showing the deleted slides.
         #self.assertFalse(session.materials.filter(type='slides',states__type__slug='slides',states__slug='deleted').first().get_absolute_url() in unicontent(r))
 
@@ -183,12 +183,6 @@ class MeetingTests(TestCase):
         self.assertTrue(session.group.acronym in agenda_content)
         self.assertTrue(slot.location.name in agenda_content)
 
-        # document-specific urls
-        for doc in session.materials.exclude(states__slug='deleted'):
-            url = urlreverse('ietf.meeting.views.materials_document', kwargs=dict(num=meeting.number, document=doc.name))
-            r = self.client.get(url)
-            self.assertEqual(unicontent(r), doc.text())
-
     def test_agenda_current_audio(self):
         date = datetime.date.today()
         meeting = MeetingFactory(type_id='ietf', date=date )
@@ -276,14 +270,14 @@ class MeetingTests(TestCase):
         self.write_materials_files(meeting, session)
         
         # session agenda
-        r = self.client.get(urlreverse("ietf.meeting.views.session_agenda",
-                                       kwargs=dict(num=meeting.number, session=session.group.acronym)))
+        r = self.client.get(urlreverse("ietf.meeting.views.materials_document",
+                                       kwargs=dict(num=meeting.number, document=session.agenda())))
         self.assertEqual(r.status_code, 200)
         self.assertTrue("1. WG status" in unicontent(r))
 
         # session minutes
-        r = self.client.get(urlreverse("ietf.meeting.views.session_minutes",
-                                       kwargs=dict(num=meeting.number, session=session.group.acronym)))
+        r = self.client.get(urlreverse("ietf.meeting.views.materials_document",
+                                       kwargs=dict(num=meeting.number, document=session.minutes())))
         self.assertEqual(r.status_code, 200)
         self.assertTrue("1. More work items underway" in unicontent(r))
 
@@ -322,6 +316,12 @@ class MeetingTests(TestCase):
             # FIXME: missing tests of .pdf/.tar generation (some code can
             # probably be lifted from similar tests in iesg/tests.py)
 
+            # document-specific urls
+            for doc in session.materials.exclude(states__slug='deleted'):
+                url = urlreverse('ietf.meeting.views.materials_document', kwargs=dict(num=meeting.number, document=doc.name))
+                r = self.client.get(url)
+                self.assertEqual(unicontent(r), doc.text())
+
     def test_materials_editable_groups(self):
         meeting = make_meeting_test_data()
         
diff --git a/ietf/meeting/urls.py b/ietf/meeting/urls.py
index 0e268ec0d..6f68ad7f6 100644
--- a/ietf/meeting/urls.py
+++ b/ietf/meeting/urls.py
@@ -50,8 +50,6 @@ type_ietf_only_patterns = [
     url(r'^agendas.json$',                       ajax.agenda_infosurl),
     url(r'^agenda/(?P<session>[A-Za-z0-9-]+)-drafts.pdf$', views.session_draft_pdf),
     url(r'^agenda/(?P<session>[A-Za-z0-9-]+)-drafts.tgz$', views.session_draft_tarfile),
-    url(r'^agenda/(?P<session>[A-Za-z0-9-]+)/?$', views.session_agenda),
-    url(r'^minutes/(?P<session>[A-Za-z0-9-]+)/?$', views.session_minutes),
     url(r'^sessions.json',                               ajax.sessions_json),
     url(r'^session/(?P<sessionid>\d+).json',             ajax.session_json),
     url(r'^session/(?P<sessionid>\d+)/constraints.json', ajax.session_constraints),
@@ -63,8 +61,7 @@ type_ietf_only_patterns = [
 type_interim_patterns = [
     url(r'^agenda/(?P<session>[A-Za-z0-9-]+)-drafts.pdf$', views.session_draft_pdf),
     url(r'^agenda/(?P<session>[A-Za-z0-9-]+)-drafts.tgz$', views.session_draft_tarfile),
-    url(r'^agenda/(?P<session>[A-Za-z0-9-]+)/?$', views.session_agenda),
-    url(r'^minutes/(?P<session>[A-Za-z0-9-]+)/?$', views.session_minutes),
+    url(r'^materials/%(document)s$' % settings.URL_REGEXPS, views.materials_document),
 ]
 
 type_ietf_only_patterns_id_optional = [
diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py
index 1412c1aa0..079d32973 100644
--- a/ietf/meeting/views.py
+++ b/ietf/meeting/views.py
@@ -60,6 +60,7 @@ from ietf.meeting.utils import finalize
 from ietf.secr.proceedings.utils import handle_upload_file
 from ietf.secr.proceedings.proc_utils import (get_progress_stats, post_process, import_audio_files,
     import_youtube_video_urls)
+from ietf.utils import log
 from ietf.utils.mail import send_mail_message
 from ietf.utils.pipe import pipe
 from ietf.utils.pdf import pdf_pages
@@ -160,11 +161,7 @@ def current_materials(request):
 def materials_document(request, document, num=None, ):
     if num is None:
         num = get_meeting(num).number
-    if re.search('-[0-9][0-9]$', document):
-        name = document[:-3]
-    else:
-        name = document
-    doc = get_object_or_404(Document, name=name)
+    doc = get_object_or_404(Document, name=document)
     if not doc.meeting_related():
         raise Http404("Not a meeting related document")
     if not doc.session_set.filter(meeting__number=num).exists():
@@ -625,6 +622,7 @@ def agenda_by_type_ics(request,num=None,type=None):
     return render(request,"meeting/agenda.ics",{"schedule":schedule,"updated":updated,"assignments":assignments},content_type="text/calendar")
 
 def session_document(request, num, acronym, type="agenda"):
+    log.unreachable("2017-07-22")
     d = Document.objects.filter(type=type, session__meeting__number=num)
     if acronym == "plenaryt":
         d = d.filter(session__name__icontains="technical", session__slots__type="plenary")
@@ -665,9 +663,11 @@ def session_document(request, num, acronym, type="agenda"):
     raise Http404("No %s for the %s session of IETF %s is available" % (type, acronym, num))
 
 def session_agenda(request, num, session):
+    log.unreachable("2017-07-22")
     return session_document(request, num, acronym=session, type='agenda')
 
 def session_minutes(request, num, session):
+    log.unreachable("2017-07-22")
     return session_document(request, num, acronym=session, type='minutes')
 
 def session_draft_list(num, session):
@@ -1522,7 +1522,7 @@ def upload_session_slides(request, session_id, num, name):
                         name += '-%s' % (session.docname_token(),)
                 else:
                     name = 'slides-%s-%s' % (session.meeting.number, session.docname_token())
-                name = name + '-' + slugify(title)
+                name = name + '-' + slugify(title).replace('_', '-')
                 if Document.objects.filter(name=name).exists():
                    doc = Document.objects.get(name=name)
                    doc.rev = '%02d' % (int(doc.rev)+1)
diff --git a/ietf/settings.py b/ietf/settings.py
index fb5042901..221a576c1 100644
--- a/ietf/settings.py
+++ b/ietf/settings.py
@@ -543,7 +543,7 @@ URL_REGEXPS = {
     "charter": r"(?P<name>charter-[-a-z0-9]+)",
     "date": r"(?P<date>\d{4}-\d{2}-\d{2})",
     "name": r"(?P<name>([A-Za-z0-9_+-]+?|%s))" % DRAFT_NAMES_WITH_DOT,
-    "document": r"(?P<document>[a-z][-a-z0-9]+)", # regular document names
+    "document": r"(?P<document>[a-z][-a-z0-9_]+)", # regular document names
     "rev": r"(?P<rev>[0-9]{1,2}(-[0-9]{2})?)",
     "owner": r"(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)",
     "schedule_name": r"(?P<name>[A-Za-z0-9-:_]+)",
diff --git a/ietf/templates/meeting/agenda.html b/ietf/templates/meeting/agenda.html
index cb6e4bf63..237748792 100644
--- a/ietf/templates/meeting/agenda.html
+++ b/ietf/templates/meeting/agenda.html
@@ -226,7 +226,7 @@
 		    <span class="hidden-xs">
 		      {% if item.timeslot.type.slug == 'other' %}
 			{% for slide in item.session.slides %}
-			  <a href="{{slide.get_absolute_url}}">{{ slide.title|clean_whitespace }}</a>
+			  <a href="{{slide.href}}">{{ slide.title|clean_whitespace }}</a>
 			  <br>
 			{% endfor %}
 		      {% endif %}
diff --git a/ietf/templates/meeting/agenda.ics b/ietf/templates/meeting/agenda.ics
index 71b80df3b..a5b153168 100644
--- a/ietf/templates/meeting/agenda.ics
+++ b/ietf/templates/meeting/agenda.ics
@@ -11,11 +11,11 @@ CLASS:PUBLIC
 DTSTART{% if schedule.meeting.time_zone %};TZID="{{schedule.meeting.time_zone}}"{%endif%}:{{ item.timeslot.time|date:"Ymd" }}T{{item.timeslot.time|date:"Hi"}}00
 DTEND{% if schedule.meeting.time_zone %};TZID="{{schedule.meeting.time_zone}}"{%endif%}:{{ item.timeslot.end_time|date:"Ymd" }}T{{item.timeslot.end_time|date:"Hi"}}00
 DTSTAMP:{{ item.timeslot.modified|date:"Ymd" }}T{{ item.timeslot.modified|date:"His" }}Z
-{% if item.session.agenda %}URL:{{item.session.agenda.get_absolute_url}}
+{% if item.session.agenda %}URL:{{item.session.agenda.href}}
 DESCRIPTION:{{item.timeslot.name|ics_esc}}\n{% if item.session.agenda_note %}
  Note: {{item.session.agenda_note|ics_esc}}\n{% endif %}{% for material in item.session.materials.all %}
  \n{{material.type}}{% if material.type.name != "Agenda" %}
   ({{material.title|ics_esc}}){% endif %}:
-  {{material.get_absolute_url}}\n{% endfor %}
+  {{material.href}}\n{% endfor %}
 {% endif %}END:VEVENT
 {% endif %}{% endfor %}END:VCALENDAR{% endautoescape %}
diff --git a/ietf/templates/meeting/room-view.html b/ietf/templates/meeting/room-view.html
index 0400dad39..0d036ed34 100644
--- a/ietf/templates/meeting/room-view.html
+++ b/ietf/templates/meeting/room-view.html
@@ -24,7 +24,7 @@
   {% for ss in assignments %}
      if (room_names.indexOf("{{ss.timeslot.get_hidden_location}}") >= 0 )
      {
-       items.push({room_index:room_names.indexOf("{{ss.timeslot.get_hidden_location}}"),day:{{ss.day}}, delta_from_beginning:{{ss.delta_from_beginning}},time:"{{ss.timeslot.time|date:"Hi"}}-{{ss.timeslot.end_time|date:"Hi"}}", verbose_time:"{{ss.timeslot.time|date:"D M d Hi"}}-{{ss.timeslot.end_time|date:"Hi"}}",duration:{{ss.timeslot.duration.total_seconds}}, type:"{{ss.timeslot.type}}", {% if ss.session.name %}name:"{{ss.session.name|escapejs}}",{% if ss.session.group.acronym %} wg:"{{ss.session.group.acronym}}",{%endif%}{% else %}{% if ss.timeslot.type.name == "Break" %}name:"{{ss.timeslot.name|escapejs}}", area:"break", wg:"break",{% elif ss.timeslot.type.slug == "unavail" %}name:"Unavailable",{% else %}name:"{{ss.session.group.name|escapejs}}{%if ss.session.group.state.name == "BOF"%} BOF{%endif%}",wg:"{{ss.session.group.acronym}}",state:"{{ss.session.group.state}}",area:"{{ss.session.group.parent.acronym}}",{% endif %}{% endif %} dayname:"{{ ss.timeslot.time|date:"l"|upper }}, {{ ss.timeslot.time|date:"F j, Y" }}"{% if ss.session.agenda %}, agenda:"{{ss.session.agenda.get_absolute_url}}"{% endif %} });
+       items.push({room_index:room_names.indexOf("{{ss.timeslot.get_hidden_location}}"),day:{{ss.day}}, delta_from_beginning:{{ss.delta_from_beginning}},time:"{{ss.timeslot.time|date:"Hi"}}-{{ss.timeslot.end_time|date:"Hi"}}", verbose_time:"{{ss.timeslot.time|date:"D M d Hi"}}-{{ss.timeslot.end_time|date:"Hi"}}",duration:{{ss.timeslot.duration.total_seconds}}, type:"{{ss.timeslot.type}}", {% if ss.session.name %}name:"{{ss.session.name|escapejs}}",{% if ss.session.group.acronym %} wg:"{{ss.session.group.acronym}}",{%endif%}{% else %}{% if ss.timeslot.type.name == "Break" %}name:"{{ss.timeslot.name|escapejs}}", area:"break", wg:"break",{% elif ss.timeslot.type.slug == "unavail" %}name:"Unavailable",{% else %}name:"{{ss.session.group.name|escapejs}}{%if ss.session.group.state.name == "BOF"%} BOF{%endif%}",wg:"{{ss.session.group.acronym}}",state:"{{ss.session.group.state}}",area:"{{ss.session.group.parent.acronym}}",{% endif %}{% endif %} dayname:"{{ ss.timeslot.time|date:"l"|upper }}, {{ ss.timeslot.time|date:"F j, Y" }}"{% if ss.session.agenda %}, agenda:"{{ss.session.agenda.href}}"{% endif %} });
      }
   {% endfor %}
   {% endautoescape %}
diff --git a/ietf/templates/meeting/upcoming.ics b/ietf/templates/meeting/upcoming.ics
index 33a5aa993..7b42d2e48 100644
--- a/ietf/templates/meeting/upcoming.ics
+++ b/ietf/templates/meeting/upcoming.ics
@@ -11,11 +11,11 @@ CLASS:PUBLIC
 DTSTART{% if item.schedule.meeting.time_zone %};TZID="{{item.schedule.meeting.time_zone}}"{%endif%}:{{ item.timeslot.time|date:"Ymd" }}T{{item.timeslot.time|date:"Hi"}}00
 DTEND{% if item.schedule.meeting.time_zone %};TZID="{{item.schedule.meeting.time_zone}}"{%endif%}:{{ item.timeslot.end_time|date:"Ymd" }}T{{item.timeslot.end_time|date:"Hi"}}00
 DTSTAMP:{{ item.timeslot.modified|date:"Ymd" }}T{{ item.timeslot.modified|date:"His" }}Z
-{% if item.session.agenda %}URL:{{item.session.agenda.get_absolute_url}}
+{% if item.session.agenda %}URL:{{item.session.agenda.href}}
 DESCRIPTION:{{item.timeslot.name|ics_esc}}\n{% if item.session.agenda_note %}
  Note: {{item.session.agenda_note|ics_esc}}\n{% endif %}{% for material in item.session.materials.all %}
  \n{{material.type}}{% if material.type.name != "Agenda" %}
   ({{material.title|ics_esc}}){% endif %}:
-  {{material.get_absolute_url}}\n{% endfor %}
+  {{material.href}}\n{% endfor %}
 {% endif %}END:VEVENT
 {% endfor %}END:VCALENDAR{% endautoescape %}