Blob Blame History Raw
#!/usr/bin/python
#
# Xhtml.output -- This module encapsulates XHTML output code needed by
# web applications.
#
# Copyright (C) 2009, 2010, 2011 The CentOS Project
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# ----------------------------------------------------------------------
# $Id$
# ----------------------------------------------------------------------

import os
import cgi
import cgitb; cgitb.enable()
from datetime import date

qs = cgi.parse_qs(os.environ['QUERY_STRING'])

now = date.today()

def tag(name, attrs, indent=[8,1], content="", has_child=0):
    """Returns XHTML tag definition.

    Arguments:

    name: The XHTML tag's name. Notice that this function doesn't
        verify nor validate the XHTML tags you provide. It is up to
        you write them correctly considering the XHTML standard
        definition.

    attrs: The XHTML tag's attribute. Notice that this function
        doesn't verify the attributes assignation to tags. You need to
        know what attributes are considered valid to the tag you are
        creating in order to build a well-formed XHTML document. Such
        verification can be achived inside firefox browser through the
        `firebug' plugin.

    indent: The XHTML tag's indentation (Optional). This argument is a
        list of two numerical values. The first value in the list
        represents the amount of horizontal spaces between the
        beginning of line and the opening tag.  The second value in
        the list represents the amount of vertical spaces (new lines)
        between tags.

    content: The XHTML tag's content (Optional). This argument
        provides the information the tag encloses. When this argument
        is empty, tag is rendered without content.

    has_child: The XHTML tag has a child? (Optional). This argument is
        specifies whether a tag has another tag inside (1) or not (0).
        When a tag has not a child tag, indentation is applied between
        the tag content and the closing tag provoking an unecessary
        spaces to be shown. Such kind of problems are prevented by
        setting this option to `0'. On the other hand, when a tag has
        a child tag inside, using the value `1' will keep the closing
        tag indentation aligned with the opening one.

    This function encapsulates the construction of XHTML tags.  Use
    this function wherever you need to create XHTML tags. It helps to
    standardize tag constructions and their final output and, this
    way, produce consistent XHTML documents.

    """
    if indent[0] > 0:
        h_indent = ' '*indent[0]
    else:
        h_indent = ''

    if indent[1] > 0: 
        v_indent = "\n"*indent[1]
    else:
        v_indent = ''
    
    output = v_indent + h_indent + '<' + str(name)
    if len(attrs) > 0:
        attr_names = attrs.keys()
        attr_names.sort()
        for attr_name in attr_names:
            output += ' ' + str(attr_name) + '="' + str(attrs[attr_name]) + '"'
    if content == '':
        output += ' />'
    else:
        output += '>'
        output += str(content)
        if has_child == 1:
            output += h_indent + '</' + str(name) + '>'
        else:
            output += '</' + str(name) + '>'
    output += v_indent

    return output


def page_preamble():
    """Return XHTML code of page preamble.

    The page preamble sets the document type definition required by
    the XHTML standard.

    """
    output = '<?xml version="1.0"?>' + "\n"
    output += '<!DOCTYPE html' + "\n"
    output += ' '*4 + 'PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' + "\n"
    output += ' '*4 + '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' + "\n"

    return output


def page_logo():
    """Returns XHTML code of page logo.

    The page logo is displayed on the top-left corner of the page. We
    use this area to show The CentOS Logo, the main visual
    representation of The CentOS Project. In order to print the page
    logo correctly, the image related must be 78 pixels of height.

    """
    attrs = []
    attrs.append({'id': 'logo'})
    attrs.append({'title': 'Community Enterprise Operating System', 'href': '/centos-web/'})
    attrs.append({'src': '/centos-web-pub/Images/centos-logo.png', 'alt': 'CentOS'})

    return tag('div', attrs[0], [8,1], tag('a', attrs[1], [12,1], tag('img', attrs[2], [0,0], '', 0), 0), 1)


def page_ads_google():
    """Returns XHTML code of Google advertisement (468x60 pixels).
    
    """
    output = """
        <div class="ads-google">
            <a title="Google Advertisement" href=""><img src="/centos-web-pub/Images/ads-sample-468x60.png" alt="Google Advertisement" /></a>
            <script type="text/javascript"><!--
                google_ad_client = "pub-6973128787810819";
                google_ad_width = 468;
                google_ad_height = 60;
                google_ad_format = "468x60_as";
                google_ad_type = "text_image";
                google_ad_channel = "";
                google_color_border = "204c8d";
                google_color_bg = "345c97";
                google_color_link = "0000FF";
                google_color_text = "FFFFFF";
                google_color_url = "008000";
                //-->
            </script>
            <script type="text/javascript"
                src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
            </script>
        </div>

        <div class="page-line"><hr style="display:none;" /></div>
    """
    return output


def page_navibar_top():
    """Returns XHTML code of top-level navigation bar. 
    
    The top-level navigation bar organizes links to the web
    application The CentOS Project makes use of. Links in the
    top-level navigation bar remain always visible, no matter what web
    application you be visiting.

    Notice that web application differe one another and is not
    convenient to point them all to this definition. Instead, a
    specific definition for each web application will be created
    (based on this definition) in order for them to give the
    impression of being connected. In this process, the top-level
    navigation bar is adapted to each web application characteristics
    and the related tab is set as current.

    """
    names = []
    attrs = []

    names.append('Home')
    attrs.append({'accesskey': '1', 'title': 'The CentOS Project (Alt+Shift+1)', 'href': '/centos-web/'})
    names.append('Wiki')
    attrs.append({'accesskey': '2', 'title': 'The CentOS Wiki (Alt+Shift+2)', 'href': '/centos-web/?app=wiki'})
    names.append('Lists')
    attrs.append({'accesskey': '3', 'title': 'The CentOS Lists (Alt+Shift+3)', 'href': '/centos-web/?app=lists'})
    names.append('Forums')
    attrs.append({'accesskey': '4', 'title': 'The CentOS Forums (Alt+Shift+4)', 'href': '/centos-web/?app=forums'})
    names.append('Projects')
    attrs.append({'accesskey': '5', 'title': 'The CentOS Projects (Alt+Shift+5)', 'href': '/centos-web/?app=projects'})
    names.append('Bugs')
    attrs.append({'accesskey': '6', 'title': 'The CentOS Bugs (Alt+Shift+6)', 'href': '/centos-web/?app=bugs'})
    names.append('Docs')
    attrs.append({'accesskey': '7', 'title': 'The CentOS Documentation (Alt+Shift+7)', 'href': '/centos-web/?app=docs'})
    names.append('Downloads')
    attrs.append({'accesskey': '8', 'title': 'The CentOS Downloads (Alt+Shift+8)', 'href': '/centos-web/?app=downloads'})
    names.append('Sponsors')
    attrs.append({'accesskey': '9', 'title': 'The CentOS Downloads (Alt+Shift+9)', 'href': '/centos-web/?app=sponsors'})

    if 'app' in qs:
        focus = qs['app'][0]
    else:
        focus = names[0]

    output = page_navibar_tabs(names, attrs, focus)
    output += page_line({'class': 'page-line white'}, [8,1])

    return output


def page_navibar_tabs(names, attrs, focus="Home"):
    """Returns navigation tabs.

    Arguments:

    names: List of tab names.

    attrs: List of dictionaries for each tab name inside the `names'
        list. Dictionaries inside attrs argument contain the XHTML
        link attributes (e.g., accesskey, title, and href) used by tab
        names so they can be linkable once rendered.

    focus: Name of the tab marked as current. When no value is passed
        to this argument the `Home' value is used as default value.

    """
    navibar_tabs = ''

    for i in range(len(names)):
        content = tag('span', '', [0,0], str(names[i]))
        content = tag('a', attrs[i], [16,1], content)
        if str(names[i]).lower() == focus.lower():
            content = tag('span', {'class': 'current'}, [12,1], content, 1)
        else:
            content = tag('span', '', [12,1], content, 1)
        navibar_tabs += content

    return tag('div', {'class': 'tabs1'}, [8,1], navibar_tabs, 1)


def page_ads_release(image='ads-sample-728x90.png', description='Release Advertisement'):
    """Return last-release advertisement.
    
    The release advertisment is a 728x90 pixels image graphically
    designed to promote the last releases of The CentOS Distribution.
    This image is located on the header space, between the top-level
    links and application specific links. This image changes each time
    a new release is published from The CentOS Project and is only
    visible at home page (i.e., the first time shown when
    `http://www.centos.org/' domain is requested from a web browser).
    
    The place where the release advertisement is displayed on the web
    is an area of high visual impact, so images appearing therein
    should be carefully designed in consequence with it.  The
    frequency and priority of images in the rotation must be connected
    somehow with The CentOS Distribution releasing process.

    Previous to consider the release advertisement as such, it was
    reserved for sponsor advertisements. Nevertheless, sponsor
    advertisements were moved to a page to their own through a link in
    the top-level navegation bar.
    
    """
    attrs = []
    attrs.append({'class': 'ads-release'})
    attrs.append({'title': description, 'href': ''})
    attrs.append({'src': '/centos-web-pub/Images/' + image, 'alt': description})
    output = tag('div', attrs[0], [8,1], tag('a', attrs[1], [12,1], tag('img', attrs[2], [0,0], '', 0), 0), 1)

    return output


def page_userlinks(names=['Login'], attrs=[{'href': '/centos-web/?p=login'}]):
    """Returns user links.

    Arguments:

    names: List of links you want to have.

    attrs: List of dictionaries with link attributes. In order for
        links to be built correctly, both names and attrs lists must
        coincide their indexes.

    The user links are specific to each web application. They are
    shown in the right-top corner of the application navigation bar,
    just over the application navigation tabs.

    """
    userlinks = ''

    for i in range(len(names)):
        content = tag('a', attrs[i], [20,1], str(names[i]), 0)
        if i == len(names) - 1:
            content = tag('span', {'class': 'last'}, [16,1], content, 1)
        else:
            content = tag('span', '', [16,1], content, 1)
        userlinks += content 

    userlinks = tag('div', {'class': 'user'}, [12,1], userlinks, 1)

    return tag('div', {'class': 'links'}, [8,1], userlinks, 1)


def page_navibar_app(names=['Welcome'], attrs=[{'href':'/centos-web/?p=welcome'}]):
    """Returns application's navigation bar."""
    if 'p' in qs:
        focus = qs['p'][0]
    else:
        focus = names[0]

    navibar_app = page_navibar_tabs(names, attrs, focus)
    navibar_app += page_line({'class': 'page-line white'}, [8,1])

    return navibar_app
 

def page_breadcrumbs():
    """Returns page breadcrumbs.
    
    The page breadcrumbs record the last pages visited inside the
    current web application.

    """
    links = ''
    names = []
    attrs = []

    names.append('Pagination')
    attrs.append({'href': ''})
    names.append('Lists')
    attrs.append({'href': ''})
    names.append('Headings')
    attrs.append({'href': ''})
    names.append('Links')
    attrs.append({'href': ''})

    for i in range(len(names)):
        if i == len(names) - 1:
            content = tag('span', {'class':'last'}, [16,1], tag('a', attrs[i], [20, 1], names[i]), 1)
        else:
            content = tag('span', '', [16,1], tag('a', attrs[i], [20, 1], names[i], 0), 1)
        links = links + content

    return tag('div', {'class': 'trail'}, [12,1], links, 1)


def page_line(attrs={'class': 'page-line'}, indent=[8,1]):
    """Returns a division line."""
    page_line = tag('hr', {'style': 'display:none;'}, [0,0])
    page_line = tag('div', attrs, indent, page_line)

    return page_line


def page_title(title='The CentOS Project'):
    """Returns page title."""
    title = 'The CentOS Project'
    if 'app' in qs.keys():
        title += ' :: ' + qs['app'][0].capitalize()
    return title


def page_language(language='en'):
    """Returns page language."""
    return language


def page_keywords(keywords='centos, project, community, enterprise, operating system'):
    """Returns page keywords."""
    return keywords


def page_description(description="Community Enterprise Operating    tem"):
    """Returns page description."""
    return description


def page_copyright(copyright_year=now.strftime("%Y"), 
                   copyright_holder='The CentOS Project. All rights reserved.'):
    """Returns page copyright."""
    return copyright_year + ' ' + copyright_holder 


def page_license():
    """Retruns link to page license."""
    license = 'Creative Commons Attribution-Share Alike 3.0 Unported License.'
    license = tag('a', {'href': 'http://creativecommons.org/licenses/by-sa/3.0/'}, [0,0], license)
    return license


def page_metadata():
    """Returns page metadata."""
    metadata = tag('meta', {'http-equiv': 'content-type', 'content': 'text/html; charset=UTF-8'}, [4,1])
    metadata += tag('meta', {'http-equiv': 'content-style-type', 'content': 'text/css'}, [4,0])
    metadata += tag('meta', {'http-equiv': 'content-language', 'content': str(page_language())}, [4,1])
    metadata += tag('meta', {'name': 'keywords', 'content': str(page_keywords())}, [4,0])
    metadata += tag('meta', {'name': 'description', 'content': str(page_description())}, [4,1])
    metadata += tag('meta', {'name': 'copyright', 'content': 'Copyright © ' + str(page_copyright())}, [4,0])
    metadata += tag('title', '', [4,1], page_title())
    metadata += tag('link', {'href': '/centos-web-pub/stylesheet.css','rel': 'stylesheet', 'type': 'text/css'}, [4,1])
     
    metadata += tag('link', {'href': '/centos-web-pub/Images/centos-fav.png', 'rel': 'shortcut icon', 'type': 'image/png'}, [4,0])

    return tag('head', '', [0,1], metadata)

def page_credits():
    """Returns page credits."""
    copyright = tag('p', {'class': 'copyright'}, [12,1], 'Copyright &copy; ' + str(page_copyright()))
    license = tag('p', {'class': 'license'}, [12,1], 'This website is licensed under a ' + str(page_license()))
    credits = tag('img', {'src': '/centos-web-pub/Images/top.png', 'alt': 'Top'}, [0,0])
    credits = tag('a', {'title': 'Top', 'href': '#top'}, [16,1], credits)
    credits = tag('div', {'class': 'top'}, [12,1], credits, 1)
    credits = str(credits) + str(copyright) + str(license) 
    credits = tag('div', {'class': 'credits'}, [8,1], credits, 1)

    return credits


def page_content():
    """Returns page content."""
    content = tag('h1', {'class': 'title'}, [12, 1], page_title())
    content += tag('p', '', [12, 1], 'No content found for this page.')
    return content


def page():
    """Returns page final output."""
    page_header = page_logo()
    page_header += page_ads_google()
    page_header += page_navibar_top()
    if not 'app' in qs:
        page_header += page_ads_release()
        page_header += page_userlinks()
        page_header += page_navibar_app()
    page_header = tag('div', {'id': 'page-header'}, [4,1], page_header, 1)

    page_body = page_content() + page_line(indent=[12,1])
    page_body = tag('div', {'id':'content'}, [8,1], page_body, 1)
    page_body = tag('div', {'id':'page-body'}, [4,1], page_body, 1)

    page_footer = page_line(indent=[4,1])
    page_footer += tag('div', {'id': 'page-footer'}, [4,1], page_credits(), 1)
    
    top = tag('a', {'name':'top'}, [0,1], '')
    wrap = tag('div', {'id': 'wrap'}, [0,1], page_header + page_body + page_footer)
    body = tag('body', '', [0,1], top + wrap)

    html = page_preamble()
    html += tag('html', {'xmlns': 'http://www.w3.org/1999/xhtml', 'dir': 'ltr', 
                         'lang': str(page_language()), 'xml:lang':
                         str(page_language())}, [0,1], page_metadata() +  body)

    return html


def main():
    """The Xhtml code of a complete page."""
    print 'Content-type: text/html' + "\n"
    print page()