# -*- coding: iso-8859-15 -*-


# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
#     Romain Chantereau <rchantereau@entrouvert.com>
#     Nicolas Clapiès <nclapies@easter-eggs.org>
#     Pierre-Antoine Dejace <padejace@entrouvert.be>
#     Thierry Dulieu <tdulieu@easter-eggs.com>
#     Florent Monnier <monnier@codelutin.com>
#     Cédric Musso <cmusso@easter-eggs.org>
#     Frédéric Péters <fpeters@entrouvert.be>
#     Benjamin Poussin <poussin@codelutin.com>
#     Emmanuel Raviart <eraviart@entrouvert.com>
#     Sébastien Régnier <regnier@codelutin.com>
#     Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
#     Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
#     Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
#     Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
#     Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
#     Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
#     Régnier, Emmanuel Saracco, Théridion & Vecam
#
# 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.


from __future__ import nested_scopes


__doc__ = """Glasnost XHTML Generator"""

__version__ = '$Revision$'[11:-2]


import base64
import locale
import urlparse

import context
import faults
from tools import extractApplicationHostName, extractApplicationPort
from XhtmlGenerator import *


buttonLabels = {
    'about': N_('About Glasnost'),
    'abstain': N_('Abstain'),
    'add': N_('Add'),
    'add-article': N_('Add Article'),
    'add-candidate': N_('Add Candidate'),
    'apply': N_('Apply'),
    'back': N_('Back'),
    'cancel': N_('Cancel'),
    'change-password': N_('Change Password'),    
    'change-translation': N_('Change Translation'),
    'clone': N_('Duplicate'),
    'compute': N_('Compute'),
    'create': N_('Create'),
    'delete': N_('Delete'),
    'diff': N_('Differences'),
    'download': N_('Download Glasnost'),
    'edit': N_('Edit'),
    'edit-arguments': N_('Edit Arguments'),
    'evaluate': N_('Evaluate'),
    'all-articles': N_('All Articles'),
    'find': N_('Find'),
    'history': N_('History'),
    'implement': N_('New Implementation'),
    'license': N_('Read the License'),
    'login': N_('Login'),
    'logout': N_('Exit'),
    'modify': N_('Modify'),
    'next': N_('Next'),
    'new': N_('New'),
    'new-account': N_('New Account'),
    'ok': N_('OK'),
    'pester-abstentionnists': N_('Pester Absentionnists'),
    'post-comment': N_('Post a Comment'),
    'post-reply': N_('Reply'),
    'prefs': N_('Preferences'),
    'pretion': N_('Pretion'),
    'preview': N_('Preview'),
    'propose': N_('Submit For Evaluation'),
    'refuse': N_('Refuse'),
    'send-by-email': N_('Send by Email'),
    'send-password-by-email': N_('Send Password by Email'),
    'settings': N_('Settings'),
    'spell': N_('Spell Check'),
    'source': N_('Source'),    
    'translate': N_('Translate'),
    'update-translation': N_('Update Translation'),
    'use': N_('Use'),
    'validate': N_('Validate'),
    'version': N_('Version'),
    'view': N_('View'),
    'view-definition': N_('Definition'),
    'view-list': N_('List'),
    'view-type': N_('Type'),
    'view-widget': N_('Widget'),
    'vote': N_('Vote '),
    'vote-blank': N_('Vote Blank'),
    }


class accountingCell(td):     
    def __init__(self, text = '', **attributes):
        td.__init__(self, **attributes)
        self.append(text)               
        self.text = text
        
    def getText(self):
        return self.text

            
class accountingTable(table):     
    def __init__(self, top = '', row=[]):
        self.top = top 
        self.row = row

    def getAsXml(self):
        numCols = max(1, len(self.row))
        topTd = td(colspan = numCols)
        topTd.append([nbsp] * 4)
        topTd.append(self.top)
        topTr = tr(topTd)
        rowTr = tr(self.row)
        return table(topTr, rowTr).getAsXml()


class buttonAction:
    label = None

    def getAsXml(self, **keywords):
        # Note: onSubmit doesn't seem to work and I don't know why.
        layout = form(
                _class = 'urls-choice', action= '/load',
                method = 'post', name = 'urls-choice',
                onSubmit = 'location.href = this.form.urlsChoice.options['
                        'this.form.urlsChoice.selectedIndex].value')
        menu = select(
                name = 'urlsChoice',
                onChange = 'location.href = this.form.urlsChoice.options['
                        'this.form.urlsChoice.selectedIndex].value')
        for labelAndLink in self.getLabelsAndLinks():
            menu.append(option(value = labelAndLink[1])(labelAndLink[0]))
        layout.append(menu)
        layout.append(input(_class = 'button', type = 'submit',
                            value = _(self.label)))
        return layout.getAsXml(**keywords)


class buttonInForm:
    key = None
    name = None

    def __init__(self, key, name):
        self.key = key
        self.name = name

    def getAsXml(self, **keywords):
        if buttonLabels.has_key(self.key):
            text = _(buttonLabels[self.key]).strip()
        else:
            text = self.key
        trueTag = input(_class = 'button', name = self.name,
                         type = 'submit', value = text)
# The following solutions don't work with Internet Explorer.
##         trueTag = button(_class = 'button', name = 'button',
##                          type = 'submit', value = self.name)(text)
##         trueTag = button(_class = 'button', name = self.name,
##                          type = 'submit', value = self.name)(text)
        return trueTag.getAsXml(**keywords)


class buttonGotoObjects(buttonAction):
    label  = N_('Go')

    def getLabelsAndLinks(self):
        from glasnost.web.tools import getGotoObjectsLabelsAndLinks
        return getGotoObjectsLabelsAndLinks()


class buttonNewObject(buttonAction):
    label  = N_('Add')

    def getLabelsAndLinks(self):
        from glasnost.web.tools import getNewObjectLabelsAndLinks
        return getNewObjectLabelsAndLinks()


class buttonPopup:
    href = None
    key = None

    def __init__(self, key, href):
        self.key = key
        self.href = href

    def getAsXml(self, **keywords):
        if buttonLabels.has_key(self.key):
            text = _(buttonLabels[self.key]).strip()
        else:
            text = self.key
        jScript = "window.open('%s','comment','toolbar=no,location=no,"\
                  "directories=no,status=no,menubar=no,scrollbars=yes,"\
                  "width=566,height=333'); return false;" % self.href
        trueTag = a(_class = 'button', href = self.href, OnClick=jScript)(text)
        return trueTag.getAsXml(**keywords)


class buttonStandalone:
    href = None
    key = None

    def __init__(self, key, href):
        self.key = key
        self.href = href

    def getAsXml(self, **keywords):
        if buttonLabels.has_key(self.key):
            text = _(buttonLabels[self.key]).strip()
        else:
            text = self.key
        trueTag = a(_class = 'button', href = self.href)(text)
        return trueTag.getAsXml(**keywords)

def hContext():
    sectionLevel = context.getVar('sectionLevel')
    return globals()['h%d' % (sectionLevel+1)]

class menuIds:
    attributes = {}
    fieldValue = None
    menus = None
    roles = None
    noneLabel = N_('None')
    permanentIds = None

    def __init__(self, roles, attributes = None, fieldValue = None,
                 fullRoles = None, menus = None, noneLabel = None,
                 permanentIds = None):
        from glasnost.proxy.tools import getObjectLabelsTranslated, \
                 getProxyForServerRole

        self.roles = roles
        if attributes:
            self.attributes = attributes
        if fieldValue is not None:
            self.fieldValue = fieldValue
        if menus is None:
            self.menus = {}
        else:
            self.menus = menus
        if noneLabel is not None:
            self.noneLabel = noneLabel
        if permanentIds is not None:
            self.permanentIds = permanentIds

        if not self.menus:
            for role in self.roles:
                if not role:
                    continue
                if fullRoles is not None and not role in fullRoles:
                    continue
                proxy = getProxyForServerRole(role)
                objectIds = proxy.getObjectIds()
                if role == 'groups':
                    acceptedObjectIds = []
                    for objectId in objectIds:
                        accepted = 0
                        if not proxy.canGetObject(objectId):
                            objectIds.remove(objectId)
                            continue
                        object = proxy.getObject(objectId)
                        objectAcceptedRoles = object.getSlot(
                                'acceptedRoles').getValue()
                        if not objectAcceptedRoles:
                            accepted = 1
                        elif self.roles == ['groups']:
                            accepted = 1
                        else:
                            for remainingRole in self.roles:
                                if remainingRole == 'groups':
                                    continue
                                if remainingRole in objectAcceptedRoles:
                                    accepted = 1
                        if accepted:
                            acceptedObjectIds.append(objectId)
                    objectIds = acceptedObjectIds
                self.menus[role] = getObjectLabelsTranslated(
                        objectIds, context.getVar('readLanguages'))
            user = context.getVar('user')
            if user:
                objectsMemory = user.objectsMemory
                if objectsMemory is not None:
                    for role in self.roles:
                        if not objectsMemory.has_key(role):
                            continue
                        serverMemory = objectsMemory[role]
                        if not serverMemory:
                            continue
                        if self.menus.has_key(role):
                            continue
                        self.menus[role] = getObjectLabelsTranslated(
                                serverMemory,
                                context.getVar('readLanguages'))

    def getAsXml(self, **keywords):
        from glasnost.proxy.tools import getObjectLabelTranslated
        from glasnost.web.tools import getWebForServerRole

        selectLayout = select(**self.attributes)
        optionAttributes = {}
        if not self.fieldValue:
            optionAttributes['selected'] = 'selected'
        selectLayout += option(value = '', **optionAttributes)(
                _(self.noneLabel))

        if self.fieldValue:
            objectId = self.fieldValue
            try:
                objectLabel = getObjectLabelTranslated(objectId,
                        context.getVar('readLanguages'))
            except: # TODO: tighter check
                pass
            else:
                selectLayout += option(selected = 'selected',
                        value = objectId)(objectLabel)

        if self.permanentIds:
            for permanentId in self.permanentIds:
                if permanentId == self.fieldValue:
                    continue
                try:
                    permanentLabel = getObjectLabelTranslated(permanentId,
                            context.getVar('readLanguages'))
                except: # TODO: tighter check
                    pass
                else:
                    selectLayout += option(value = permanentId)(permanentLabel)

        usedRoles = []
        roleLocalizedLabels = {}
        for role in self.roles:
            web = getWebForServerRole(role)
            if not web:
                continue
            if not self.menus.has_key(role):
                continue
            menu = self.menus[role]
            if not menu or len(menu) == 1 and menu.has_key(self.fieldValue):
                continue
            usedRoles.append(role)
            roleLocalizedLabels[role] = _(web.objectsNameCapitalized)
        usedRoles.sort(
                lambda x, y:
                locale.strcoll(roleLocalizedLabels[x], roleLocalizedLabels[y]))
        for role in usedRoles:
            menu = self.menus[role]
            if len(self.menus) > 1:
                optionsGroup = optgroup(label = roleLocalizedLabels[role])
                selectLayout += optionsGroup
            else:
                optionsGroup = selectLayout
            menuItems = menu.items()
            menuItems.sort(lambda x,y:
                           locale.strcoll(x[1].lower(), y[1].lower()))
            for objectId, objectLabel in menuItems:
                if objectId == self.fieldValue:
                    continue
                if len(objectLabel) > 80:
                    objectLabel = objectLabel[
                        : 70 + objectLabel[70:].find(' ')] + ' (...)'
                optionsGroup += option(value = objectId)(objectLabel)

        return selectLayout.getAsXml(**keywords)


def objectHypertextLabel(objectId):
    from glasnost.proxy.tools import getObjectLabelTranslated
    if not objectId:
        return ''
    try:
        label = getObjectLabelTranslated(
            objectId, context.getVar('readLanguages'))
    except faults.MissingItem:
        return span(_class = 'deleted')(_('Missing Object (%s)') % objectId)
    if commonTools.extractDispatcherId(objectId) == 'glasnost://system':
        return asIs(label)
    return a(href = idUrl(objectId))(label)
        

class smallAccountingTable(table):
    def __init__(self, side, amount=0):
        assert (side=='debit' or side=='credit')
        self.amount = str(amount) 
        self.side = side

    def getAsXml(self, parent = None, indent = 0, **keywords):
        width = 12
        td1 = td(width=width)(self.amount)
        td2 = td(width=width)(nbsp)
        r = tr()
        if self.side == 'debit':
            r.append(td1)   
            r.append(td2)
        else:   
            r.append(td2)   
            r.append(td1)        
        return table(r).getAsXml()


_httpUrl = httpUrl
class httpUrl(httpUrl):
    pathPrefix = None

    def __init__(self, protocol = None, hostNameAndPort = None,
                 hostName = None, port = None, path = None, parameters = None,
                 query = None, fragment = None):
        httpScriptDirectoryPath = context.getVar(
            'httpScriptDirectoryPath')
        if httpScriptDirectoryPath is not None:
            self.pathPrefix = httpScriptDirectoryPath
        if context.getVar('helpInUrl'):
            if self.pathPrefix is None:
                self.pathPrefix = '/help/'
            else:
                self.pathPrefix = '%shelp/' % self.pathPrefix
        _httpUrl.__init__(
            self, protocol = protocol, hostNameAndPort = hostNameAndPort,
            hostName = hostName, port = port, path = path,
            parameters = parameters, query = query, fragment = fragment)

    def getArgumentNames(self):
        argumentNames = _httpUrl.getArgumentNames(self)
        canUseCookie = context.getVar('canUseCookie', default = 0)
        sessionToken = context.getVar('sessionToken')
        if not canUseCookie:
            if sessionToken is not None \
                   and not 'sessionToken' in argumentNames:
                argumentNames.append('sessionToken')
        elif 'sessionToken' in argumentNames:
            argumentNames.remove('sessionToken')
        return argumentNames

    def getArguments(self):
        canUseCookie = context.getVar('canUseCookie', default = 0)
        sessionToken = context.getVar('sessionToken')
        if not canUseCookie:
            if sessionToken is not None:
                self.argument_sessionToken = sessionToken

        arguments = _httpUrl.getArguments(self)

        if not canUseCookie:
            if sessionToken is not None:
                del self.argument_sessionToken
        return arguments

    def getPath(self, **keywords):
        if self.pathPrefix is not None:
            pathPrefix = self.pathPrefix
        else:
            pathPrefix = context.getVar(
                'httpScriptDirectoryPath')
            if pathPrefix is None:
                pathPrefix = '/'
            if context.getVar('helpInUrl'):
                pathPrefix = '%shelp/' % pathPrefix
        path = _httpUrl.getPath(self, **keywords)
        if path and path[0] == '/':
            path = path[1:]
        path = '%s%s' % (pathPrefix, path)
        return path


class rootUrl(httpUrl):
    dispatcherHostName = None
    dispatcherPort = None

    def __init__(self, hostNameAndPort = None, hostName = None, port = None):
        if hostNameAndPort:
            infos = hostNameAndPort.split(':', 1)
            hostName = infos[0]
            if len(infos) < 2:
                port = None
            else:
                port = infos[1]
        if hostName is not None:
            self.dispatcherHostName = hostName
        else:
            dispatcherId = context.getVar('defaultDispatcherId')
            if dispatcherId is None:
                dispatcherId = context.getVar('dispatcherId')
            if dispatcherId is not None:
                dispatcherHostName = extractApplicationHostName(dispatcherId)
                self.dispatcherHostName = dispatcherHostName
        if port is not None:
            self.dispatcherPort = str(port)
        else:
            dispatcherId = context.getVar('defaultDispatcherId')
            if dispatcherId is None:
                dispatcherId = context.getVar('dispatcherId')
            if dispatcherId is not None:
                dispatcherPort = str(extractApplicationPort(dispatcherId))
                self.dispatcherPort = dispatcherPort
        self.remoteSso = context.getVar('remoteSso')

    def getPath(self, **keywords):
        httpScriptDirectoryPath = context.getVar('httpScriptDirectoryPath')
        if httpScriptDirectoryPath is None:
            httpScriptDirectoryPath = '/'
        dispatcherId = context.getVar('defaultDispatcherId')
        if dispatcherId is None:
            dispatcherId = context.getVar('dispatcherId')
        if dispatcherId is not None:
            dispatcherHostName = extractApplicationHostName(dispatcherId)
            dispatcherPort = str(extractApplicationPort(dispatcherId))
        else:
            dispatcherHostName = None
            dispatcherPort = None

        if self.dispatcherHostName in ['help', 'system'] or (
                (self.dispatcherHostName is None
                 or self.dispatcherHostName == dispatcherHostName)
                and (self.dispatcherPort is None
                     or self.dispatcherPort == dispatcherPort)):
            result = httpScriptDirectoryPath
        else:
            if self.dispatcherHostName is not None:
                dispatcherHostName = self.dispatcherHostName
            elif dispatcherHostName is None:
                dispatcherHostName = 'localhost'
            if self.dispatcherPort is not None:
                dispatcherPort = self.dispatcherPort
            if dispatcherPort is None \
                   or dispatcherPort == str(context.getVar('dispatcherPort')):
                dispatcherHostNameAndPort = dispatcherHostName
            else:
                dispatcherHostNameAndPort = '%s:%s' % (
                        dispatcherHostName, dispatcherPort)
            if self.remoteSso:
                result = '%sremote-sso/%s/' % (
                        httpScriptDirectoryPath, dispatcherHostNameAndPort)
            else:
                result = '%sremote/%s/' % (
                        httpScriptDirectoryPath, dispatcherHostNameAndPort)
        if context.getVar('helpInUrl'):
            result = '%shelp/' % result
        if context.getVar('languageSetInUrl') \
               and not 'ignoreLanguage' in keywords.keys():
            result = '%s%s/' % (result, context.getVar('readLanguages')[0])
        return result


class aliasUrl(rootUrl):
    action = None
    alias = None

    def __init__(self, alias, action = None):
        import tools_new as commonTools
        dispatcherId = context.getVar('defaultDispatcherId')
        if dispatcherId is None:
            dispatcherId = context.getVar('dispatcherId')
        hostNameAndPort = commonTools.extractHostNameAndPort(dispatcherId)

        rootUrl.__init__(self, hostNameAndPort = hostNameAndPort)

        assert alias
        self.alias = alias
        if action:
            self.action = action

    def getPath(self, **keywords):
        path = rootUrl.getPath(self, **keywords)

        templatePrefix = context.getVar('templatePrefix')
        if templatePrefix:
            if self.action:
                action = '/%s%s' % (templatePrefix, self.action)
            else:
                action = '/%sview' % templatePrefix
        else:
            if self.action:
                action = '/%s' % self.action
            else:
                action = ''
        return '%s%s%s' % (path, self.alias, action)


class fileUrl(rootUrl):
    filename = None

    def __init__(self, filename):
        rootUrl.__init__(self)
        self.filename = filename

    def getPath(self, **keywords):
        path = rootUrl.getPath(self, ignoreLanguage = 1, **keywords)
        if path[-1] == '/' and self.filename[0] == '/':
            path = path[:-1]
        return path + self.filename


class idUrl(rootUrl):
    action = None
    localId = None
    role = None
    id = None

    def __init__(self, id, action = None):
        import tools_new as commonTools
        if id:
            role = commonTools.extractRole(id)
            localId = commonTools.extractLocalId(id)
            self.id = id
        else:
            id = context.getVar('defaultDispatcherId')
            if id is None:
                id = context.getVar('dispatcherId')
            role = context.getVar('serverRole')
            localId = None
        hostNameAndPort = commonTools.extractHostNameAndPort(id)

        rootUrl.__init__(self, hostNameAndPort = hostNameAndPort)

        if role:
            self.role = role
        if localId:
            self.localId = localId
        if action:
            self.action = action

    def getPath(self, **keywords):
        try:
            from glasnost.web.tools import getWebForServerRole
            roleWeb = getWebForServerRole(self.role)
        except ImportError:
            roleWeb = None
        if roleWeb and hasattr(roleWeb, 'idUrl') and (
                not keywords or not keywords.has_key('ignoreWeb')):
            return roleWeb.idUrl(self)
            
        knownRoles = context.getVar('knownRoles')
        if knownRoles and 'pagenames' in knownRoles:
            from glasnost.proxy.tools import getProxyForServerRole
            pageNamesProxy = getProxyForServerRole('pagenames')
            if pageNamesProxy:
                dispatcherId = context.getVar('defaultDispatcherId')
                defaultDispatcherId = context.getVar('defaultDispatcherId')
                if defaultDispatcherId is None:
                    defaultDispatcherId = context.getVar('dispatcherId')
                if defaultDispatcherId is not None \
                       and defaultDispatcherId != dispatcherId:
                    # This is a remote id. Search for a local alias.
                    applicationId = commonTools.makeApplicationId(
                            defaultDispatcherId, self.role)
                    if self.localId:
                        id = '%s/%s' % (applicationId, self.localId)
                    else:
                        id = applicationId
                    try:
                        alias = pageNamesProxy.getNameByMappedId(id)
                    except faults.UnknownServerId:
                        alias = None
                    if alias:
                        return aliasUrl(alias, self.action).getPath()

        path = rootUrl.getPath(self, **keywords)

        templatePrefix = context.getVar('templatePrefix')
        if templatePrefix:
            if self.action:
                action = '/%s%s' % (templatePrefix, self.action)
            else:
                action = '/%sview' % templatePrefix
        else:
            if self.action:
                action = '/%s' % self.action
            else:
                action = ''

        if knownRoles and 'pagenames' in knownRoles and pageNamesProxy:
            if dispatcherId is None:
                dispatcherId = context.getVar('dispatcherId')
            if dispatcherId is not None:
                applicationId = commonTools.makeApplicationId(
                    dispatcherId, self.role)
                if self.localId:
                    id = '%s/%s' % (applicationId, self.localId)
                else:
                    id = applicationId
                try:
                    alias = pageNamesProxy.getNameByMappedId(id)
                except faults.UnknownServerId:
                    alias = None
                if alias:
                    return aliasUrl(alias, self.action).getPath()

            dispatcherId = 'glasnost://%s' % self.dispatcherHostName
            applicationId = commonTools.makeApplicationId(
                    dispatcherId, self.role)
            if self.localId:
                id = '%s/%s' % (applicationId, self.localId)
            else:
                id = applicationId
            alias = pageNamesProxy.getNameByMappedId(id)
            if alias:
                return '%s%s%s' % (path, alias, action)

        if self.role:
            role = self.role
        else:
            role = ''
        if self.localId:
            localId = '/%s' % self.localId
        else:
            localId = ''
        return '%s%s%s%s' % (path, role, localId, action)


def absoluteUrl(s):
    if s.startswith('glasnost://'):
        return idUrl(s)
    else:
        assert s.startswith('http')
        return url(s)


def actionUrl(action = None):
    return idUrl(None, action)


def roleUrl(role, action = None):
    dispatcherId = context.getVar('dispatcherId')
    if dispatcherId is None:
        dispatcherId = context.getVar('defaultDispatcherId')
    if not role:
        role = context.getVar('serverRole')
    serverId = commonTools.makeApplicationId(dispatcherId, role)
    return idUrl(serverId, action)


def url(s):
    parsedUrl = urlparse.urlparse(s)
    if parsedUrl[0]:
        protocol = parsedUrl[0]
    else:
        protocol = None
    if parsedUrl[1]:
        hostNameAndPort = parsedUrl[1]
    else:
        hostNameAndPort = None
    if parsedUrl[2]:
        path = parsedUrl[2]
    else:
        path = None
    if parsedUrl[3]:
        parameters = parsedUrl[3]
    else:
        parameters = None
    if parsedUrl[4]:
        query = parsedUrl[4]
    else:
        query = None
    if parsedUrl[5]:
        fragment = parsedUrl[5]
    else:
        fragment = None
    return httpUrl(
            protocol = protocol, hostNameAndPort = hostNameAndPort,
            path = path, parameters = parameters, query = query,
            fragment = fragment)

