Esempio n. 1
0
def default_approval_text(status_change,relateddoc):

    filename = "%s-%s.txt" % (status_change.canonical_name(), status_change.rev)
    current_text = get_document_content(filename, os.path.join(settings.STATUS_CHANGE_PATH, filename), split=False, markup=False)

    if relateddoc.target.document.std_level.slug in ('std','ps','ds','bcp',):
        action = "Protocol Action"
    else:
        action = "Document Action"


    addrs = gather_address_lists('ballot_approved_status_change',doc=status_change).as_strings(compact=False)
    text = render_to_string("doc/status_change/approval_text.txt",
                               dict(status_change=status_change,
                                    status_change_url = settings.IDTRACKER_BASE_URL+status_change.get_absolute_url(),
                                    relateddoc= relateddoc,
                                    relateddoc_url = settings.IDTRACKER_BASE_URL+relateddoc.target.document.get_absolute_url(),
                                    approved_text = current_text,
                                    action=action,
                                    newstatus=newstatus(relateddoc),
                                    to=addrs.to,
                                    cc=addrs.cc,
                                   )
                              )

    return text
Esempio n. 2
0
File: views.py Progetto: ekr/ietfdb
def get_doc_writeup(doc):
    '''
    This function takes a Document object and returns the ballot writeup for display
    in the detail view.  In the case of Conflict Review documents we actually
    want to display the contents of the document
    '''
    writeup = 'This document has no writeup'
    if doc.type_id == 'draft':
        latest = doc.latest_event(WriteupDocEvent,
                                  type='changed_ballot_writeup_text')
        if latest:
            writeup = latest.text
            if doc.has_rfc_editor_note():
                rfced_note = doc.latest_event(
                    WriteupDocEvent, type="changed_rfc_editor_note_text")
                writeup = writeup + "\n\n" + rfced_note.text
    if doc.type_id == 'charter':
        latest = doc.latest_event(WriteupDocEvent,
                                  type='changed_ballot_writeup_text')
        if latest:
            writeup = latest.text
    elif doc.type_id == 'conflrev':
        path = os.path.join(doc.get_file_path(), doc.filename_with_rev())
        writeup = get_document_content(doc.name,
                                       path,
                                       split=False,
                                       markup=False)
    return writeup
Esempio n. 3
0
def default_approval_text(review):

    filename = "%s-%s.txt" % (review.canonical_name(), review.rev)
    current_text = get_document_content(filename,
                                        os.path.join(
                                            settings.CONFLICT_REVIEW_PATH,
                                            filename),
                                        split=False,
                                        markup=False)

    conflictdoc = review.relateddocument_set.get(
        relationship__slug='conflrev').target.document
    if conflictdoc.stream_id == 'ise':
        receiver = 'RFC-Editor'
    elif conflictdoc.stream_id == 'irtf':
        receiver = 'IRTF'
    else:
        receiver = 'recipient'
    text = render_to_string(
        "doc/conflict_review/approval_text.txt",
        dict(review=review,
             review_url=settings.IDTRACKER_BASE_URL +
             review.get_absolute_url(),
             conflictdoc=conflictdoc,
             conflictdoc_url=settings.IDTRACKER_BASE_URL +
             conflictdoc.get_absolute_url(),
             receiver=receiver,
             approved_review=current_text))

    return text
Esempio n. 4
0
def email_charter_internal_review(request, charter):
    addrs = gather_address_lists('charter_internal_review',doc=charter,group=charter.group)
    filename = '%s-%s.txt' % (charter.canonical_name(),charter.rev)
    charter_text = get_document_content(
                        filename,
                        os.path.join(settings.CHARTER_PATH,filename),
                        split=False,
                        markup=False,
                   )
    send_mail(request, addrs.to, settings.DEFAULT_FROM_EMAIL,
              'Internal %s Review: %s (%s)'%(charter.group.type.name,charter.group.name,charter.group.acronym),
              'doc/mail/charter_internal_review.txt',
              dict(charter=charter,
                   charter_text=charter_text,
                   review_type = "new" if charter.group.state_id == "proposed" else "recharter",
                   charter_url=settings.IDTRACKER_BASE_URL + charter.get_absolute_url(),
                   chairs=charter.group.role_set.filter(name="chair"),
                   secr=charter.group.role_set.filter(name="secr"),
                   ads=charter.group.role_set.filter(name='ad').values_list('person__name',flat=True),
                   techadv=charter.group.role_set.filter(name="techadv"),
                   milestones=charter.group.groupmilestone_set.filter(state="charter"),
              ),
              cc=addrs.cc,
              extra={'Reply-To':"*****@*****.**"},
             )
Esempio n. 5
0
File: views.py Progetto: mcr/ietfdb
def get_doc_writeup(doc):
    '''
    This function takes a Document object and returns the ballot writeup for display
    in the detail view.  In the case of Conflict Review documents we actually
    want to display the contents of the document
    '''
    writeup = 'This document has no writeup'
    if doc.type_id in ('draft','charter'):
        latest = doc.latest_event(WriteupDocEvent, type='changed_ballot_writeup_text')
        if latest:
            writeup = latest.text
    elif doc.type_id == 'conflrev':
        path = os.path.join(doc.get_file_path(),doc.filename_with_rev())
        writeup = get_document_content(doc.name,path,split=False,markup=False)
    return writeup
Esempio n. 6
0
File: forms.py Progetto: ekr/ietfdb
 def __init__(self, *args, **kwargs):
     if 'user' in kwargs:
         self.user = kwargs.pop('user')
     if 'group' in kwargs:
         self.group = kwargs.pop('group')
     if 'is_approved_or_virtual' in kwargs:
         self.is_approved_or_virtual = kwargs.pop('is_approved_or_virtual')
     super(InterimSessionModelForm, self).__init__(*args, **kwargs)
     self.is_edit = bool(self.instance.pk)
     # setup fields that aren't intrinsic to the Session object
     if self.is_edit:
         self.initial['date'] = self.instance.official_timeslotassignment().timeslot.time
         self.initial['time'] = self.instance.official_timeslotassignment().timeslot.time
         if self.instance.agenda():
             doc = self.instance.agenda()
             path = os.path.join(doc.get_file_path(), doc.filename_with_rev())
             self.initial['agenda'] = get_document_content(os.path.basename(path), path, markup=False)
Esempio n. 7
0
def default_approval_text(status_change, relateddoc):

    filename = "%s-%s.txt" % (status_change.canonical_name(),
                              status_change.rev)
    current_text = get_document_content(filename,
                                        os.path.join(
                                            settings.STATUS_CHANGE_PATH,
                                            filename),
                                        split=False,
                                        markup=False)

    if relateddoc.target.document.std_level.slug in (
            'std',
            'ps',
            'ds',
            'bcp',
    ):
        action = "Protocol Action"
    else:
        action = "Document Action"

    addrs = gather_address_lists('ballot_approved_status_change',
                                 doc=status_change).as_strings(compact=False)
    text = render_to_string(
        "doc/status_change/approval_text.txt",
        dict(
            status_change=status_change,
            status_change_url=settings.IDTRACKER_BASE_URL +
            status_change.get_absolute_url(),
            relateddoc=relateddoc,
            relateddoc_url=settings.IDTRACKER_BASE_URL +
            relateddoc.target.document.get_absolute_url(),
            approved_text=current_text,
            action=action,
            newstatus=newstatus(relateddoc),
            to=addrs.to,
            cc=addrs.cc,
        ))

    return text
Esempio n. 8
0
def default_approval_text(review):

    filename = "%s-%s.txt" % (review.canonical_name(), review.rev)
    current_text = get_document_content(filename, os.path.join(settings.CONFLICT_REVIEW_PATH, filename), split=False, markup=False)

    conflictdoc = review.relateddocument_set.get(relationship__slug='conflrev').target.document
    if conflictdoc.stream_id=='ise':
         receiver = 'RFC-Editor'
    elif conflictdoc.stream_id=='irtf':
         receiver = 'IRTF'
    else:
         receiver = 'recipient'
    text = render_to_string("doc/conflict_review/approval_text.txt",
                               dict(review=review,
                                    review_url = settings.IDTRACKER_BASE_URL+review.get_absolute_url(),
                                    conflictdoc = conflictdoc,
                                    conflictdoc_url = settings.IDTRACKER_BASE_URL+conflictdoc.get_absolute_url(),
                                    receiver=receiver,
                                    approved_review = current_text
                                   )
                              )

    return text
Esempio n. 9
0
File: mails.py Progetto: ekr/ietfdb
def email_charter_internal_review(request, charter):
    addrs = gather_address_lists('charter_internal_review',
                                 doc=charter,
                                 group=charter.group)
    filename = '%s-%s.txt' % (charter.canonical_name(), charter.rev)
    charter_text = get_document_content(
        filename,
        os.path.join(settings.CHARTER_PATH, filename),
        split=False,
        markup=False,
    )
    send_mail(
        request,
        addrs.to,
        settings.DEFAULT_FROM_EMAIL,
        'Internal %s Review: %s (%s)' %
        (charter.group.type.name, charter.group.name, charter.group.acronym),
        'doc/mail/charter_internal_review.txt',
        dict(
            charter=charter,
            charter_text=charter_text,
            review_type="new"
            if charter.group.state_id == "proposed" else "recharter",
            charter_url=settings.IDTRACKER_BASE_URL +
            charter.get_absolute_url(),
            chairs=charter.group.role_set.filter(name="chair"),
            secr=charter.group.role_set.filter(name="secr"),
            ads=charter.group.role_set.filter(name='ad'),
            parent_ads=charter.group.parent.role_set.filter(name='ad'),
            techadv=charter.group.role_set.filter(name="techadv"),
            milestones=charter.group.groupmilestone_set.filter(
                state="charter"),
        ),
        cc=addrs.cc,
        extra={'Reply-To': "*****@*****.**"},
    )
Esempio n. 10
0
def document_content(doc):
    if doc is None:
        return None
    path = os.path.join(doc.get_file_path(), doc.filename_with_rev())
    return get_document_content(doc.name, path, markup=False)
Esempio n. 11
0
def document_main(request, name, rev=None):
    doc = get_object_or_404(Document.objects.select_related(), docalias__name=name)

    # take care of possible redirections
    aliases = DocAlias.objects.filter(document=doc).values_list("name", flat=True)
    if doc.type_id == "draft" and not name.startswith("rfc"):
        for a in aliases:
            if a.startswith("rfc"):
                return redirect("doc_view", name=a)

    group = doc.group
    if doc.type_id == 'conflrev':
        conflictdoc = doc.related_that_doc('conflrev')[0].document
    
    revisions = []
    for h in doc.history_set.order_by("time", "id"):
        if h.rev and not h.rev in revisions:
            revisions.append(h.rev)
    if not doc.rev in revisions:
        revisions.append(doc.rev)

    snapshot = False

    if rev != None:
        if rev == doc.rev:
            return redirect('doc_view', name=name)

        # find the entry in the history
        for h in doc.history_set.order_by("-time"):
            if rev == h.rev:
                snapshot = True
                doc = h
                break

        if not snapshot:
            return redirect('doc_view', name=name)

        if doc.type_id == "charter":
            # find old group, too
            gh = find_history_active_at(doc.group, doc.time)
            if gh:
                group = gh

    top = render_document_top(request, doc, "document", name)


    telechat = doc.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
    if telechat and (not telechat.telechat_date or telechat.telechat_date < datetime.date.today()):
       telechat = None


    # specific document types
    if doc.type_id == "draft":
        split_content = not ( request.GET.get('include_text') or request.COOKIES.get("full_draft", "") == "on" )

        iesg_state = doc.get_state("draft-iesg")
        iesg_state_summary = doc.friendly_state()
        can_edit = has_role(request.user, ("Area Director", "Secretariat"))
        stream_slugs = StreamName.objects.values_list("slug", flat=True)
        can_change_stream = bool(can_edit or (
                request.user.is_authenticated() and
                Role.objects.filter(name__in=("chair", "secr", "auth", "delegate"),
                                    group__acronym__in=stream_slugs,
                                    person__user=request.user)))
        can_edit_iana_state = has_role(request.user, ("Secretariat", "IANA"))

        rfc_number = name[3:] if name.startswith("") else None
        draft_name = None
        for a in aliases:
            if a.startswith("draft"):
                draft_name = a

        rfc_aliases = [prettify_std_name(a) for a in aliases
                       if a.startswith("fyi") or a.startswith("std") or a.startswith("bcp")]

        latest_revision = None

        if doc.get_state_slug() == "rfc":
            # content
            filename = name + ".txt"

            content = get_document_content(filename, os.path.join(settings.RFC_PATH, filename),
                                           split_content, markup=True)

            # file types
            base_path = os.path.join(settings.RFC_PATH, name + ".")
            possible_types = ["txt", "pdf", "ps"]
            found_types = [t for t in possible_types if os.path.exists(base_path + t)]

            base = "http://www.rfc-editor.org/rfc/"

            file_urls = []
            for t in found_types:
                label = "plain text" if t == "txt" else t
                file_urls.append((label, base + name + "." + t))

            if "pdf" not in found_types and "txt" in found_types:
                file_urls.append(("pdf", base + "pdfrfc/" + name + ".txt.pdf"))

            if "txt" in found_types:
                file_urls.append(("html", "http://tools.ietf.org/html/" + name))

            if not found_types:
                content = "This RFC is not currently available online."
                split_content = False
            elif "txt" not in found_types:
                content = "This RFC is not available in plain text format."
                split_content = False
        else:
            filename = "%s-%s.txt" % (draft_name, doc.rev)

            content = get_document_content(filename, os.path.join(settings.INTERNET_DRAFT_PATH, filename),
                                           split_content, markup=True)

            # file types
            base_path = os.path.join(settings.INTERNET_DRAFT_PATH, doc.name + "-" + doc.rev + ".")
            possible_types = ["pdf", "xml", "ps"]
            found_types = ["txt"] + [t for t in possible_types if os.path.exists(base_path + t)]

            tools_base = "http://tools.ietf.org/"

            if doc.get_state_slug() == "active":
                base = "http://www.ietf.org/id/"
            else:
                base = tools_base + "id/"

            file_urls = []
            for t in found_types:
                label = "plain text" if t == "txt" else t
                file_urls.append((label, base + doc.name + "-" + doc.rev + "." + t))

            if "pdf" not in found_types:
                file_urls.append(("pdf", tools_base + "pdf/" + doc.name + "-" + doc.rev + ".pdf"))
            file_urls.append(("html", tools_base + "html/" + doc.name + "-" + doc.rev))

            # latest revision
            latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")

        # ballot
        ballot_summary = None
        if iesg_state and iesg_state.slug in IESG_BALLOT_ACTIVE_STATES:
            active_ballot = doc.active_ballot()
            if active_ballot:
                ballot_summary = needed_ballot_positions(doc, active_ballot.active_ad_positions().values())

        # submission
        submission = ""
        if group is None:
            submission = "unknown"
        elif group.type_id == "individ":
            submission = "individual"
        elif group.type_id == "area" and doc.stream_id == "ietf":
            submission = "individual in %s area" % group.acronym
        elif group.type_id in ("rg", "wg"):
            submission = "%s %s" % (group.acronym, group.type)
            if group.type_id == "wg":
                submission = "<a href=\"%s\">%s</a>" % (urlreverse("group_home", kwargs=dict(group_type=doc.group.type_id, acronym=doc.group.acronym)), submission)
            if doc.stream_id and doc.get_state_slug("draft-stream-%s" % doc.stream_id) == "c-adopt":
                submission = "candidate for %s" % submission

        # resurrection
        resurrected_by = None
        if doc.get_state_slug() == "expired":
            e = doc.latest_event(type__in=("requested_resurrect", "completed_resurrect"))
            if e and e.type == "requested_resurrect":
                resurrected_by = e.by

        # stream info
        stream_state_type_slug = None
        stream_state = None
        if doc.stream:
            stream_state_type_slug = "draft-stream-%s" % doc.stream_id
            stream_state = doc.get_state(stream_state_type_slug)
        stream_tags = doc.tags.filter(slug__in=get_tags_for_stream_id(doc.stream_id))

        shepherd_writeup = doc.latest_event(WriteupDocEvent, type="changed_protocol_writeup")

        can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
        can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd) or has_role(request.user, ["Area Director"])
        can_edit_consensus = False

        consensus = None
        if doc.stream_id == "ietf" and iesg_state:
            show_in_states = set(IESG_BALLOT_ACTIVE_STATES)
            show_in_states.update(('approved','ann','rfcqueue','pub'))
            if iesg_state.slug in show_in_states: 
                can_edit_consensus = can_edit
                e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
                consensus = nice_consensus(e and e.consensus)
        elif doc.stream_id in ("irtf", "iab"):
            can_edit_consensus = can_edit or can_edit_stream_info
            e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
            consensus = nice_consensus(e and e.consensus)

        # mailing list search archive
        search_archive = "www.ietf.org/mail-archive/web/"
        if doc.stream_id == "ietf" and group.type_id == "wg" and group.list_archive:
            search_archive = group.list_archive

        search_archive = urllib.quote(search_archive, safe="~")

        # conflict reviews
        conflict_reviews = [d.document.name for d in doc.related_that("conflrev")]

        status_change_docs = doc.related_that(status_change_relationships)
        status_changes = [ rel.document for rel in status_change_docs  if rel.document.get_state_slug() in ('appr-sent','appr-pend')]
        proposed_status_changes = [ rel.document for rel in status_change_docs  if rel.document.get_state_slug() in ('needshep','adrev','iesgeval','defer','appr-pr')]

        # remaining actions
        actions = []

        if can_adopt_draft(request.user, doc):
            actions.append(("Adopt in Group", urlreverse('doc_adopt_draft', kwargs=dict(name=doc.name))))

        if doc.get_state_slug() == "expired" and not resurrected_by and can_edit:
            actions.append(("Request Resurrect", urlreverse('doc_request_resurrect', kwargs=dict(name=doc.name))))

        if doc.get_state_slug() == "expired" and has_role(request.user, ("Secretariat",)):
            actions.append(("Resurrect", urlreverse('doc_resurrect', kwargs=dict(name=doc.name))))

        if (doc.get_state_slug() != "expired" and doc.stream_id in ("ise", "irtf")
            and can_edit_stream_info and not conflict_reviews):
            label = "Begin IETF Conflict Review"
            if not doc.intended_std_level:
                label += " (note that intended status is not set)"
            actions.append((label, urlreverse('conflict_review_start', kwargs=dict(name=doc.name))))

        if (doc.get_state_slug() != "expired" and doc.stream_id in ("iab", "ise", "irtf")
            and can_edit_stream_info):
            label = "Request Publication"
            if not doc.intended_std_level:
                label += " (note that intended status is not set)"
            if iesg_state and iesg_state.slug != 'dead':
                label += " (Warning: the IESG state indicates ongoing IESG processing)"
            actions.append((label, urlreverse('doc_request_publication', kwargs=dict(name=doc.name))))

        if doc.get_state_slug() != "expired" and doc.stream_id in ("ietf",):
            if not iesg_state and can_edit:
                actions.append(("Begin IESG Processing", urlreverse('doc_edit_info', kwargs=dict(name=doc.name)) + "?new=1"))
            elif can_edit_stream_info and (not iesg_state or iesg_state.slug == 'watching'):
                actions.append(("Submit to IESG for Publication", urlreverse('doc_to_iesg', kwargs=dict(name=doc.name))))

        tracking_document = False
        if request.user.is_authenticated():
            try:
                clist = CommunityList.objects.get(user=request.user)
                clist.update()
                if clist.get_documents().filter(name=doc.name).count() > 0:
                    tracking_document = True
            except ObjectDoesNotExist:
                pass

        return render_to_response("doc/document_draft.html",
                                  dict(doc=doc,
                                       group=group,
                                       top=top,
                                       name=name,
                                       content=content,
                                       split_content=split_content,
                                       revisions=revisions,
                                       snapshot=snapshot,
                                       latest_revision=latest_revision,

                                       can_edit=can_edit,
                                       can_change_stream=can_change_stream,
                                       can_edit_stream_info=can_edit_stream_info,
                                       can_edit_shepherd_writeup=can_edit_shepherd_writeup,
                                       can_edit_iana_state=can_edit_iana_state,
                                       can_edit_consensus=can_edit_consensus,

                                       rfc_number=rfc_number,
                                       draft_name=draft_name,
                                       telechat=telechat,
                                       ballot_summary=ballot_summary,
                                       submission=submission,
                                       resurrected_by=resurrected_by,

                                       replaces=[d.name for d in doc.related_that_doc("replaces")],
                                       replaced_by=[d.name for d in doc.related_that("replaces")],
                                       updates=[prettify_std_name(d.name) for d in doc.related_that_doc("updates")],
                                       updated_by=[prettify_std_name(d.document.canonical_name()) for d in doc.related_that("updates")],
                                       obsoletes=[prettify_std_name(d.name) for d in doc.related_that_doc("obs")],
                                       obsoleted_by=[prettify_std_name(d.document.canonical_name()) for d in doc.related_that("obs")],
                                       conflict_reviews=conflict_reviews,
                                       status_changes=status_changes,
                                       proposed_status_changes=proposed_status_changes,
                                       rfc_aliases=rfc_aliases,
                                       has_errata=doc.tags.filter(slug="errata"),
                                       published=doc.latest_event(type="published_rfc"),
                                       file_urls=file_urls,
                                       stream_state_type_slug=stream_state_type_slug,
                                       stream_state=stream_state,
                                       stream_tags=stream_tags,
                                       milestones=doc.groupmilestone_set.filter(state="active"),
                                       consensus=consensus,
                                       iesg_state=iesg_state,
                                       iesg_state_summary=iesg_state_summary,
                                       rfc_editor_state=doc.get_state("draft-rfceditor"),
                                       iana_review_state=doc.get_state("draft-iana-review"),
                                       iana_action_state=doc.get_state("draft-iana-action"),
                                       started_iesg_process=doc.latest_event(type="started_iesg_process"),
                                       shepherd_writeup=shepherd_writeup,
                                       search_archive=search_archive,
                                       actions=actions,
                                       tracking_document=tracking_document,
                                       ),
                                  context_instance=RequestContext(request))

    if doc.type_id == "charter":
        filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)

        content = get_document_content(filename, os.path.join(settings.CHARTER_PATH, filename), split=False, markup=True)

        ballot_summary = None
        if doc.get_state_slug() in ("intrev", "iesgrev"):
            active_ballot = doc.active_ballot()
            if active_ballot:
                ballot_summary = needed_ballot_positions(doc, active_ballot.active_ad_positions().values())
            else:
                ballot_summary = "No active ballot found."

        chartering = get_chartering_type(doc)

        # inject milestones from group
        milestones = None
        if chartering and not snapshot:
            milestones = doc.group.groupmilestone_set.filter(state="charter")

        can_manage = can_manage_group_type(request.user, doc.group.type_id)

        return render_to_response("doc/document_charter.html",
                                  dict(doc=doc,
                                       top=top,
                                       chartering=chartering,
                                       content=content,
                                       txt_url=doc.href(),
                                       revisions=revisions,
                                       snapshot=snapshot,
                                       telechat=telechat,
                                       ballot_summary=ballot_summary,
                                       group=group,
                                       milestones=milestones,
                                       can_manage=can_manage,
                                       ),
                                  context_instance=RequestContext(request))

    if doc.type_id == "conflrev":
        filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
        pathname = os.path.join(settings.CONFLICT_REVIEW_PATH,filename)

        if doc.rev == "00" and not os.path.isfile(pathname):
            # This could move to a template
            content = "A conflict review response has not yet been proposed."
        else:     
            content = get_document_content(filename, pathname, split=False, markup=True)

        ballot_summary = None
        if doc.get_state_slug() in ("iesgeval"):
            ballot_summary = needed_ballot_positions(doc, doc.active_ballot().active_ad_positions().values())

        return render_to_response("doc/document_conflict_review.html",
                                  dict(doc=doc,
                                       top=top,
                                       content=content,
                                       revisions=revisions,
                                       snapshot=snapshot,
                                       telechat=telechat,
                                       conflictdoc=conflictdoc,
                                       ballot_summary=ballot_summary,
                                       approved_states=('appr-reqnopub-pend','appr-reqnopub-sent','appr-noprob-pend','appr-noprob-sent')
                                       ),
                                  context_instance=RequestContext(request))

    if doc.type_id == "statchg":
        filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
        pathname = os.path.join(settings.STATUS_CHANGE_PATH,filename)

        if doc.rev == "00" and not os.path.isfile(pathname):
            # This could move to a template
            content = "Status change text has not yet been proposed."
        else:     
            content = get_document_content(filename, pathname, split=False)

        ballot_summary = None
        if doc.get_state_slug() in ("iesgeval"):
            ballot_summary = needed_ballot_positions(doc, doc.active_ballot().active_ad_positions().values())
     
        if isinstance(doc,Document):
            sorted_relations=doc.relateddocument_set.all().order_by('relationship__name')
        elif isinstance(doc,DocHistory):
            sorted_relations=doc.relateddochistory_set.all().order_by('relationship__name')
        else:
            sorted_relations=None

        return render_to_response("doc/document_status_change.html",
                                  dict(doc=doc,
                                       top=top,
                                       content=content,
                                       revisions=revisions,
                                       snapshot=snapshot,
                                       telechat=telechat,
                                       ballot_summary=ballot_summary,
                                       approved_states=('appr-pend','appr-sent'),
                                       sorted_relations=sorted_relations,
                                       ),
                                  context_instance=RequestContext(request))

    if doc.type_id in ("slides", "agenda", "minutes"):
        can_manage_material = can_manage_materials(request.user, doc.group)
        if doc.meeting_related():
            # disallow editing meeting-related stuff through this
            # interface for the time being
            can_manage_material = False
            basename = doc.canonical_name() # meeting materials are unversioned at the moment
            if doc.external_url:
                # we need to remove the extension for the globbing below to work
                basename = os.path.splitext(doc.external_url)[0]
        else:
            basename = "%s-%s" % (doc.canonical_name(), doc.rev)

        pathname = os.path.join(doc.get_file_path(), basename)

        content = None
        other_types = []
        globs = glob.glob(pathname + ".*")
        for g in globs:
            extension = os.path.splitext(g)[1]
            t = os.path.splitext(g)[1].lstrip(".")
            url = doc.href()
            if not url.endswith("/") and not url.endswith(extension):
                url += extension

            if extension == ".txt":
                content = get_document_content(basename, pathname + extension, split=False)
                t = "plain text"

            other_types.append((t, url))

        return render_to_response("doc/document_material.html",
                                  dict(doc=doc,
                                       top=top,
                                       content=content,
                                       revisions=revisions,
                                       snapshot=snapshot,
                                       can_manage_material=can_manage_material,
                                       other_types=other_types,
                                       ),
                                  context_instance=RequestContext(request))

    raise Http404