Blame Scripts/CentOS-Web/Xhtml/output.py

cc10e6
#!/usr/bin/python
cc10e6
#
7e8dd3
# Xhtml.output -- This module encapsulates XHTML output code needed by
7e8dd3
# web applications.
cc10e6
#
cc10e6
# Copyright (C) 2009, 2010, 2011 The CentOS Project
cc10e6
#
cc10e6
# This program is free software; you can redistribute it and/or modify
cc10e6
# it under the terms of the GNU General Public License as published by
cc10e6
# the Free Software Foundation; either version 2 of the License, or (at
cc10e6
# your option) any later version.
cc10e6
#
cc10e6
# This program is distributed in the hope that it will be useful, but
cc10e6
# WITHOUT ANY WARRANTY; without even the implied warranty of
cc10e6
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
cc10e6
# General Public License for more details.
cc10e6
#
cc10e6
# You should have received a copy of the GNU General Public License
cc10e6
# along with this program; if not, write to the Free Software
cc10e6
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
cc10e6
#
cc10e6
# ----------------------------------------------------------------------
cc10e6
# $Id$
cc10e6
# ----------------------------------------------------------------------
cc10e6
cc10e6
import os
cc10e6
import cgi
cc10e6
import cgitb; cgitb.enable()
2da041
from datetime import date
cc10e6
cc10e6
qs = cgi.parse_qs(os.environ['QUERY_STRING'])
cc10e6
2da041
now = date.today()
2da041
7e8dd3
def tag(name, attrs, indent=[8,1], content="", has_child=0):
cc10e6
    """Returns XHTML tag definition.
cc10e6
cc10e6
    Arguments:
cc10e6
cc10e6
    name: The XHTML tag's name. Notice that this function doesn't
cc10e6
        verify nor validate the XHTML tags you provide. It is up to
cc10e6
        you write them correctly considering the XHTML standard
cc10e6
        definition.
cc10e6
7e8dd3
    attrs: The XHTML tag's attribute. Notice that this function
cc10e6
        doesn't verify the attributes assignation to tags. You need to
cc10e6
        know what attributes are considered valid to the tag you are
cc10e6
        creating in order to build a well-formed XHTML document. Such
cc10e6
        verification can be achived inside firefox browser through the
cc10e6
        `firebug' plugin.
cc10e6
7e8dd3
    indent: The XHTML tag's indentation (Optional). This argument is a
7e8dd3
        list of two numerical values. The first value in the list
cc10e6
        represents the amount of horizontal spaces between the
cc10e6
        beginning of line and the opening tag.  The second value in
cc10e6
        the list represents the amount of vertical spaces (new lines)
cc10e6
        between tags.
cc10e6
cc10e6
    content: The XHTML tag's content (Optional). This argument
cc10e6
        provides the information the tag encloses. When this argument
cc10e6
        is empty, tag is rendered without content.
cc10e6
cc10e6
    has_child: The XHTML tag has a child? (Optional). This argument is
cc10e6
        specifies whether a tag has another tag inside (1) or not (0).
cc10e6
        When a tag has not a child tag, indentation is applied between
cc10e6
        the tag content and the closing tag provoking an unecessary
cc10e6
        spaces to be shown. Such kind of problems are prevented by
cc10e6
        setting this option to `0'. On the other hand, when a tag has
cc10e6
        a child tag inside, using the value `1' will keep the closing
cc10e6
        tag indentation aligned with the opening one.
cc10e6
cc10e6
    This function encapsulates the construction of XHTML tags.  Use
cc10e6
    this function wherever you need to create XHTML tags. It helps to
cc10e6
    standardize tag constructions and their final output and, this
cc10e6
    way, produce consistent XHTML documents.
cc10e6
cc10e6
    """
7e8dd3
    if indent[0] > 0:
7e8dd3
        h_indent = ' '*indent[0]
cc10e6
    else:
cc10e6
        h_indent = ''
cc10e6
7e8dd3
    if indent[1] > 0: 
7e8dd3
        v_indent = "\n"*indent[1]
cc10e6
    else:
cc10e6
        v_indent = ''
cc10e6
    
cc10e6
    output = v_indent + h_indent + '<' + str(name)
7e8dd3
    if len(attrs) > 0:
7e8dd3
        attr_names = attrs.keys()
7e8dd3
        attr_names.sort()
7e8dd3
        for attr_name in attr_names:
7e8dd3
            output += ' ' + str(attr_name) + '="' + str(attrs[attr_name]) + '"'
cc10e6
    if content == '':
d1cf1c
        output += ' />'
cc10e6
    else:
d1cf1c
        output += '>'
d1cf1c
        output += str(content)
cc10e6
        if has_child == 1:
d1cf1c
            output += h_indent + '</' + str(name) + '>'
cc10e6
        else:
d1cf1c
            output += '</' + str(name) + '>'
d1cf1c
    output += v_indent
cc10e6
cc10e6
    return output
cc10e6
cc10e6
cc10e6
def page_preamble():
7e8dd3
    """Return XHTML code of page preamble.
cc10e6
7e8dd3
    The page preamble sets the document type definition required by
7e8dd3
    the XHTML standard.
cc10e6
cc10e6
    """
cc10e6
    output = '' + "\n"
d1cf1c
    output += '
d1cf1c
    output += ' '*4 + 'PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' + "\n"
d1cf1c
    output += ' '*4 + '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' + "\n"
cc10e6
cc10e6
    return output
cc10e6
cc10e6
cc10e6
def page_logo():
7e8dd3
    """Returns XHTML code of page logo.
cc10e6
cc10e6
    The page logo is displayed on the top-left corner of the page. We
cc10e6
    use this area to show The CentOS Logo, the main visual
cc10e6
    representation of The CentOS Project. In order to print the page
cc10e6
    logo correctly, the image related must be 78 pixels of height.
7e8dd3
cc10e6
    """
cc10e6
    attrs = []
cc10e6
    attrs.append({'id': 'logo'})
cc10e6
    attrs.append({'title': 'Community Enterprise Operating System', 'href': '/centos-web/'})
cc10e6
    attrs.append({'src': '/centos-web-pub/Images/centos-logo.png', 'alt': 'CentOS'})
cc10e6
cc10e6
    return tag('div', attrs[0], [8,1], tag('a', attrs[1], [12,1], tag('img', attrs[2], [0,0], '', 0), 0), 1)
cc10e6
cc10e6
cc10e6
def page_ads_google():
7e8dd3
    """Returns XHTML code of Google advertisement (468x60 pixels).
cc10e6
    
cc10e6
    """
cc10e6
    output = """
cc10e6
        
cc10e6
            Google Advertisement
cc10e6
            <script type="text/javascript">
cc10e6
                google_ad_client = "pub-6973128787810819";
cc10e6
                google_ad_width = 468;
cc10e6
                google_ad_height = 60;
cc10e6
                google_ad_format = "468x60_as";
cc10e6
                google_ad_type = "text_image";
cc10e6
                google_ad_channel = "";
cc10e6
                google_color_border = "204c8d";
cc10e6
                google_color_bg = "345c97";
cc10e6
                google_color_link = "0000FF";
cc10e6
                google_color_text = "FFFFFF";
cc10e6
                google_color_url = "008000";
cc10e6
                //-->
cc10e6
            </script>
cc10e6
            
cc10e6
                src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
cc10e6
            </script>
cc10e6
        
cc10e6
cc10e6
        

cc10e6
    """
cc10e6
    return output
cc10e6
cc10e6
cc10e6
def page_navibar_top():
7e8dd3
    """Returns XHTML code of top-level navigation bar. 
cc10e6
    
7e8dd3
    The top-level navigation bar organizes links to the web
7e8dd3
    application The CentOS Project makes use of. Links in the
7e8dd3
    top-level navigation bar remain always visible, no matter what web
7e8dd3
    application you be visiting.
7e8dd3
7e8dd3
    Notice that web application differe one another and is not
7e8dd3
    convenient to point them all to this definition. Instead, a
7e8dd3
    specific definition for each web application will be created
7e8dd3
    (based on this definition) in order for them to give the
7e8dd3
    impression of being connected. In this process, the top-level
7e8dd3
    navigation bar is adapted to each web application characteristics
7e8dd3
    and the related tab is set as current.
cc10e6
cc10e6
    """
cc10e6
    names = []
cc10e6
    attrs = []
cc10e6
cc10e6
    names.append('Home')
cc10e6
    attrs.append({'accesskey': '1', 'title': 'The CentOS Project (Alt+Shift+1)', 'href': '/centos-web/'})
cc10e6
    names.append('Wiki')
cc10e6
    attrs.append({'accesskey': '2', 'title': 'The CentOS Wiki (Alt+Shift+2)', 'href': '/centos-web/?app=wiki'})
cc10e6
    names.append('Lists')
cc10e6
    attrs.append({'accesskey': '3', 'title': 'The CentOS Lists (Alt+Shift+3)', 'href': '/centos-web/?app=lists'})
cc10e6
    names.append('Forums')
cc10e6
    attrs.append({'accesskey': '4', 'title': 'The CentOS Forums (Alt+Shift+4)', 'href': '/centos-web/?app=forums'})
cc10e6
    names.append('Projects')
cc10e6
    attrs.append({'accesskey': '5', 'title': 'The CentOS Projects (Alt+Shift+5)', 'href': '/centos-web/?app=projects'})
cc10e6
    names.append('Bugs')
cc10e6
    attrs.append({'accesskey': '6', 'title': 'The CentOS Bugs (Alt+Shift+6)', 'href': '/centos-web/?app=bugs'})
de0f25
    names.append('Docs')
de0f25
    attrs.append({'accesskey': '7', 'title': 'The CentOS Documentation (Alt+Shift+7)', 'href': '/centos-web/?app=docs'})
cc10e6
    names.append('Downloads')
cc10e6
    attrs.append({'accesskey': '8', 'title': 'The CentOS Downloads (Alt+Shift+8)', 'href': '/centos-web/?app=downloads'})
cc10e6
    names.append('Sponsors')
cc10e6
    attrs.append({'accesskey': '9', 'title': 'The CentOS Downloads (Alt+Shift+9)', 'href': '/centos-web/?app=sponsors'})
cc10e6
cc10e6
    if 'app' in qs:
cc10e6
        focus = qs['app'][0]
cc10e6
    else:
cc10e6
        focus = names[0]
cc10e6
cc10e6
    output = page_navibar_tabs(names, attrs, focus)
7e8dd3
    output += page_line({'class': 'page-line white'}, [8,1])
cc10e6
cc10e6
    return output
cc10e6
cc10e6
cc10e6
def page_navibar_tabs(names, attrs, focus="Home"):
7e8dd3
    """Returns navigation tabs.
cc10e6
7e8dd3
    Arguments:
cc10e6
cc10e6
    names: List of tab names.
cc10e6
cc10e6
    attrs: List of dictionaries for each tab name inside the `names'
cc10e6
        list. Dictionaries inside attrs argument contain the XHTML
cc10e6
        link attributes (e.g., accesskey, title, and href) used by tab
cc10e6
        names so they can be linkable once rendered.
cc10e6
cc10e6
    focus: Name of the tab marked as current. When no value is passed
cc10e6
        to this argument the `Home' value is used as default value.
cc10e6
cc10e6
    """
7e8dd3
    navibar_tabs = ''
cc10e6
7e8dd3
    for i in range(len(names)):
7e8dd3
        content = tag('span', '', [0,0], str(names[i]))
7e8dd3
        content = tag('a', attrs[i], [16,1], content)
7e8dd3
        if str(names[i]).lower() == focus.lower():
cc10e6
            content = tag('span', {'class': 'current'}, [12,1], content, 1)
cc10e6
        else:
cc10e6
            content = tag('span', '', [12,1], content, 1)
7e8dd3
        navibar_tabs += content
cc10e6
7e8dd3
    return tag('div', {'class': 'tabs1'}, [8,1], navibar_tabs, 1)
cc10e6
cc10e6
7e8dd3
def page_ads_release(image='ads-sample-728x90.png', description='Release Advertisement'):
7e8dd3
    """Return last-release advertisement.
cc10e6
    
cc10e6
    The release advertisment is a 728x90 pixels image graphically
cc10e6
    designed to promote the last releases of The CentOS Distribution.
cc10e6
    This image is located on the header space, between the top-level
cc10e6
    links and application specific links. This image changes each time
7e8dd3
    a new release is published from The CentOS Project and is only
7e8dd3
    visible at home page (i.e., the first time shown when
7e8dd3
    `http://www.centos.org/' domain is requested from a web browser).
cc10e6
    
cc10e6
    The place where the release advertisement is displayed on the web
cc10e6
    is an area of high visual impact, so images appearing therein
7e8dd3
    should be carefully designed in consequence with it.  The
7e8dd3
    frequency and priority of images in the rotation must be connected
7e8dd3
    somehow with The CentOS Distribution releasing process.
cc10e6
cc10e6
    Previous to consider the release advertisement as such, it was
cc10e6
    reserved for sponsor advertisements. Nevertheless, sponsor
7e8dd3
    advertisements were moved to a page to their own through a link in
cc10e6
    the top-level navegation bar.
cc10e6
    
cc10e6
    """
cc10e6
    attrs = []
cc10e6
    attrs.append({'class': 'ads-release'})
7e8dd3
    attrs.append({'title': description, 'href': ''})
7e8dd3
    attrs.append({'src': '/centos-web-pub/Images/' + image, 'alt': description})
cc10e6
    output = tag('div', attrs[0], [8,1], tag('a', attrs[1], [12,1], tag('img', attrs[2], [0,0], '', 0), 0), 1)
cc10e6
cc10e6
    return output
cc10e6
cc10e6
7e8dd3
def page_userlinks(names=['Login'], attrs=[{'href': '/centos-web/?p=login'}]):
7e8dd3
    """Returns user links.
cc10e6
7e8dd3
    Arguments:
7e8dd3
7e8dd3
    names: List of links you want to have.
cc10e6
7e8dd3
    attrs: List of dictionaries with link attributes. In order for
7e8dd3
        links to be built correctly, both names and attrs lists must
7e8dd3
        coincide their indexes.
cc10e6
7e8dd3
    The user links are specific to each web application. They are
7e8dd3
    shown in the right-top corner of the application navigation bar,
7e8dd3
    just over the application navigation tabs.
7e8dd3
7e8dd3
    """
7e8dd3
    userlinks = ''
7e8dd3
7e8dd3
    for i in range(len(names)):
7e8dd3
        content = tag('a', attrs[i], [20,1], str(names[i]), 0)
7e8dd3
        if i == len(names) - 1:
cc10e6
            content = tag('span', {'class': 'last'}, [16,1], content, 1)
cc10e6
        else:
cc10e6
            content = tag('span', '', [16,1], content, 1)
7e8dd3
        userlinks += content 
cc10e6
7e8dd3
    userlinks = tag('div', {'class': 'user'}, [12,1], userlinks, 1)
cc10e6
7e8dd3
    return tag('div', {'class': 'links'}, [8,1], userlinks, 1)
cc10e6
cc10e6
7e8dd3
def page_navibar_app(names=['Welcome'], attrs=[{'href':'/centos-web/?p=welcome'}]):
7e8dd3
    """Returns application's navigation bar."""
cc10e6
    if 'p' in qs:
cc10e6
        focus = qs['p'][0]
cc10e6
    else:
cc10e6
        focus = names[0]
cc10e6
7e8dd3
    navibar_app = page_navibar_tabs(names, attrs, focus)
7e8dd3
    navibar_app += page_line({'class': 'page-line white'}, [8,1])
cc10e6
7e8dd3
    return navibar_app
7e8dd3
 
cc10e6
7e8dd3
def page_breadcrumbs():
7e8dd3
    """Returns page breadcrumbs.
cc10e6
    
7e8dd3
    The page breadcrumbs record the last pages visited inside the
7e8dd3
    current web application.
cc10e6
cc10e6
    """
cc10e6
    links = ''
cc10e6
    names = []
cc10e6
    attrs = []
cc10e6
cc10e6
    names.append('Pagination')
cc10e6
    attrs.append({'href': ''})
cc10e6
    names.append('Lists')
cc10e6
    attrs.append({'href': ''})
cc10e6
    names.append('Headings')
cc10e6
    attrs.append({'href': ''})
cc10e6
    names.append('Links')
cc10e6
    attrs.append({'href': ''})
cc10e6
7e8dd3
    for i in range(len(names)):
7e8dd3
        if i == len(names) - 1:
7e8dd3
            content = tag('span', {'class':'last'}, [16,1], tag('a', attrs[i], [20, 1], names[i]), 1)
cc10e6
        else:
7e8dd3
            content = tag('span', '', [16,1], tag('a', attrs[i], [20, 1], names[i], 0), 1)
cc10e6
        links = links + content
cc10e6
cc10e6
    return tag('div', {'class': 'trail'}, [12,1], links, 1)
cc10e6
cc10e6
7e8dd3
def page_line(attrs={'class': 'page-line'}, indent=[8,1]):
7e8dd3
    """Returns a division line."""
7e8dd3
    page_line = tag('hr', {'style': 'display:none;'}, [0,0])
7e8dd3
    page_line = tag('div', attrs, indent, page_line)
cc10e6
7e8dd3
    return page_line
cc10e6
cc10e6
7e8dd3
def page_title(title='The CentOS Project'):
7e8dd3
    """Returns page title."""
7e8dd3
    title = 'The CentOS Project'
7e8dd3
    if 'app' in qs.keys():
7e8dd3
        title += ' :: ' + qs['app'][0].capitalize()
7e8dd3
    return title
cc10e6
cc10e6
7e8dd3
def page_language(language='en'):
7e8dd3
    """Returns page language."""
7e8dd3
    return language
cc10e6
cc10e6
2da041
def page_keywords(keywords='centos, project, community, enterprise, operating system'):
7e8dd3
    """Returns page keywords."""
7e8dd3
    return keywords
cc10e6
cc10e6
2da041
def page_description(description="Community Enterprise Operating    tem"):
7e8dd3
    """Returns page description."""
7e8dd3
    return description
cc10e6
cc10e6
2da041
def page_copyright(copyright_year=now.strftime("%Y"), 
2da041
                   copyright_holder='The CentOS Project. All rights reserved.'):
7e8dd3
    """Returns page copyright."""
2da041
    return copyright_year + ' ' + copyright_holder 
cc10e6
cc10e6
7e8dd3
def page_license():
7e8dd3
    """Retruns link to page license."""
7e8dd3
    license = 'Creative Commons Attribution-Share Alike 3.0 Unported License.'
7e8dd3
    license = tag('a', {'href': 'http://creativecommons.org/licenses/by-sa/3.0/'}, [0,0], license)
7e8dd3
    return license
cc10e6
cc10e6
7e8dd3
def page_metadata():
7e8dd3
    """Returns page metadata."""
7e8dd3
    metadata = tag('meta', {'http-equiv': 'content-type', 'content': 'text/html; charset=UTF-8'}, [4,1])
7e8dd3
    metadata += tag('meta', {'http-equiv': 'content-style-type', 'content': 'text/css'}, [4,0])
7e8dd3
    metadata += tag('meta', {'http-equiv': 'content-language', 'content': str(page_language())}, [4,1])
7e8dd3
    metadata += tag('meta', {'name': 'keywords', 'content': str(page_keywords())}, [4,0])
7e8dd3
    metadata += tag('meta', {'name': 'description', 'content': str(page_description())}, [4,1])
7e8dd3
    metadata += tag('meta', {'name': 'copyright', 'content': 'Copyright © ' + str(page_copyright())}, [4,0])
7e8dd3
    metadata += tag('title', '', [4,1], page_title())
7e8dd3
    metadata += tag('link', {'href': '/centos-web-pub/stylesheet.css', 'rel': 'stylesheet', 'type': 'text/css', 
7e8dd3
                            'media': 'screen projection'}, [4,1])
cc10e6
7e8dd3
    return tag('head', '', [0,1], metadata)
cc10e6
7e8dd3
def page_credits():
7e8dd3
    """Returns page credits."""
7e8dd3
    copyright = tag('p', {'class': 'copyright'}, [12,1], 'Copyright © ' + str(page_copyright()))
7e8dd3
    license = tag('p', {'class': 'license'}, [12,1], 'This website is licensed under a ' + str(page_license()))
7e8dd3
    credits = tag('img', {'src': '/centos-web-pub/Images/top.png', 'alt': 'Top'}, [0,0])
7e8dd3
    credits = tag('a', {'title': 'Top', 'href': '#top'}, [16,1], credits)
7e8dd3
    credits = tag('div', {'class': 'top'}, [12,1], credits, 1)
7e8dd3
    credits = str(credits) + str(copyright) + str(license) 
7e8dd3
    credits = tag('div', {'class': 'credits'}, [8,1], credits, 1)
cc10e6
7e8dd3
    return credits
cc10e6
7e8dd3
7e8dd3
def page_content():
7e8dd3
    """Returns page content."""
7e8dd3
    content = tag('h1', {'class': 'title'}, [12, 1], page_title())
7e8dd3
    content += tag('p', '', [12, 1], 'No content found for this page.')
7e8dd3
    return content
cc10e6
cc10e6
cc10e6
def page():
7e8dd3
    """Returns page final output."""
7e8dd3
    page_header = page_logo()
7e8dd3
    page_header += page_ads_google()
7e8dd3
    page_header += page_navibar_top()
7e8dd3
    if not 'app' in qs:
7e8dd3
        page_header += page_ads_release()
7e8dd3
        page_header += page_userlinks()
7e8dd3
        page_header += page_navibar_app()
7e8dd3
    page_header = tag('div', {'id': 'page-header'}, [4,1], page_header, 1)
cc10e6
7e8dd3
    page_body = page_content() + page_line(indent=[12,1])
7e8dd3
    page_body = tag('div', {'id':'content'}, [8,1], page_body, 1)
7e8dd3
    page_body = tag('div', {'id':'page-body'}, [4,1], page_body, 1)
cc10e6
7e8dd3
    page_footer = page_line(indent=[4,1])
7e8dd3
    page_footer += tag('div', {'id': 'page-footer'}, [4,1], page_credits(), 1)
7e8dd3
    
7e8dd3
    top = tag('a', {'name':'top'}, [0,1], '')
7e8dd3
    wrap = tag('div', {'id': 'wrap'}, [0,1], page_header + page_body + page_footer)
7e8dd3
    body = tag('body', '', [0,1], top + wrap)
7e8dd3
7e8dd3
    html = page_preamble()
7e8dd3
    html += tag('html', {'xmlns': 'http://www.w3.org/1999/xhtml', 'dir': 'ltr', 
7e8dd3
                         'lang': str(page_language()), 'xml:lang':
7e8dd3
                         str(page_language())}, [0,1], page_metadata() +  body)
7e8dd3
7e8dd3
    return html
7e8dd3
7e8dd3
7e8dd3
def main():
7e8dd3
    """The Xhtml code of a complete page."""
cc10e6
    print 'Content-type: text/html' + "\n"
7e8dd3
    print page()