def testBrowser(self):
        self.m_logger.info('Testing browser capabilities')

        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

        # construct the browser capabilities test page
        l_pageTemplate = EcTemplate(EcRequestHandler.cm_templateString)

        l_oldPath = self.path
        while re.search('&y=.*&', l_oldPath):
            l_oldPath = re.sub('&y=.*&', '&', self.path)
        while re.search('\?y=.*&', l_oldPath):
            l_oldPath = re.sub('\?y=.*&', '?', self.path)
        l_oldPath = re.sub('[&\?]y=.*$', '', l_oldPath)

        l_response = l_pageTemplate.substitute(
            NewTarget=re.sub('/&y', '/?y', '.' + l_oldPath + '&y={0}'.format(self.m_terminalID)),
            NewTargetRestart=re.sub('/&y', '/?y', '.' + l_oldPath + '&y=restart'),
            TestingBrowserMsg=se3_utilities.get_user_string(self.m_contextDict, 'TestingBrowserMsg'),
            GainAccess1Msg=se3_utilities.get_user_string(self.m_contextDict, 'GainAccess1Msg'),
            ThisLinkMsg=se3_utilities.get_user_string(self.m_contextDict, 'ThisLinkMsg')
        )
        # In NewTarget the re.sub above is there to handle the case where the path is a bare "/"

        self.m_logger.debug('l_response: {0}'.format(l_response))

        l_bytes = bytes(l_response, 'utf-8')
        self.m_logger.debug('Bytes to send: {0}'.format(len(l_bytes)))

        # and send it
        self.wfile.write(l_bytes)
    def badBrowserMessage(self, p_dbConnection):
        self.m_logger.info('Sending bad browser message')

        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

        # since the browser is bad, delete the terminal ID (and the test terminal ID if different)
        if 'y' in self.m_contextDict.keys():
            l_testTID = self.m_contextDict['y']
        else:
            l_testTID = ''

        l_query = """
            DELETE FROM `TB_TERMINAL`
            WHERE `TERMINAL_ID` = '{0}' or `TERMINAL_ID` = '{1}'
            ;""".format(self.m_terminalID, l_testTID)

        self.m_logger.debug('l_query: {0}'.format(l_query))
        try:
            l_cursor = p_dbConnection.cursor()
            l_cursor.execute(l_query)
            # the cursor is executed and THEN, the connection is committed
            p_dbConnection.commit()
            l_cursor.close()
        except Exception as l_exception:
            self.m_logger.warning(self.pack_massage('Something went wrong while attempting ' +
                                  'to execute this query: {0} Error: {1}'.format(
                                      l_query, l_exception.args)))

        # construct the bad browser page
        l_pageTemplate = EcTemplate(EcRequestHandler.cm_badBrowserPage)

        l_oldPath = self.path
        while re.search('&y=.*&', l_oldPath):
            l_oldPath = re.sub('&y=.*&', '&', self.path)
        while re.search('\?y=.*&', l_oldPath):
            l_oldPath = re.sub('\?y=.*&', '?', self.path)
        l_oldPath = re.sub('[&\?]y=.*$', '', l_oldPath)

        l_response = l_pageTemplate.substitute(
            LinkPrevious='.' + l_oldPath,
            NewTargetRestart=re.sub('/&y', '/?y', '.' + l_oldPath + '&y=restart'),
            BadBrowserMsg=se3_utilities.get_user_string(self.m_contextDict, 'BadBrowserMsg'),
            GainAccessMsg=se3_utilities.get_user_string(self.m_contextDict, 'GainAccessMsg'),
            ThisLinkMsg=se3_utilities.get_user_string(self.m_contextDict, 'ThisLinkMsg')
        )
        # In NewTarget the re.sub above is there to handle the case where the path is a bare "/"

        # In NewTargetRestart the re.sub() removes the y=xxxxx parameter (terminal ID used to test browser
        # capabilities). It handles both the case where y is at the end of several parameters (&y=) and
        # the case where y is directly located after / (/?y=)

        # and send it
        self.wfile.write(bytes(l_response, 'utf-8'))
def get_toc(p_previousContext, p_context, p_dbConnectionPool):
    g_loggerSE3.info("Getting TOC response")
    g_loggerSE3.debug("p_previousContext: {0}".format(p_previousContext))
    g_loggerSE3.debug("p_context: {0}".format(p_context))

    l_dbConnection = p_dbConnectionPool.getConnection()

    l_response = ""

    # Ta1 : Quran, surah number order
    # Ta2 : Quran, revelation order
    # Tb  : NT
    # Tc  : OT
    # T   : all scripture

    # For Quran, chapter ordering based on ST_ORDER (Surah number) or ST_ORDER_ALT (Revelation order)
    if p_context["K"] == "Ta1":
        # Query for Quran only: long chapter names + Translit. No need for the Book ID
        l_query = """
            select
                N_CHAPTER
                , ST_NAME_OR
                , ST_NAME_OR2
                , ST_NAME_EN
                , ST_NAME_FR
            from TB_CHAPTER
            where ID_BOOK = 'Qur'
            order by ST_ORDER
            ;"""
    elif p_context["K"] == "Ta2":
        l_query = """
            select
                N_CHAPTER
                , ST_NAME_OR
                , ST_NAME_OR2
                , ST_NAME_EN
                , ST_NAME_FR
            from TB_CHAPTER
            where ID_BOOK = 'Qur'
            order by ST_ORDER_ALT
            ;"""
    else:
        if p_context["K"] == "Tb":
            l_cond = 'ID_GROUP_0 = "NT"'
            # title for NT
            l_response += '<h1 class="TocTitle">{0}</h1>\n'.format(
                se3_utilities.get_user_string(p_context, "m_tocNTTitle")
            )
        elif p_context["K"] == "Tc":
            l_cond = 'ID_GROUP_0 = "OT"'
            # title for OT
            l_response += '<h1 class="TocTitle">{0}</h1>\n'.format(
                se3_utilities.get_user_string(p_context, "m_tocOTTitle")
            )
        else:
            l_cond = "true"
            # title for All scripture
            l_response += '<h1 class="TocTitle">{0}</h1>\n'.format(
                se3_utilities.get_user_string(p_context, "m_tocAllTitle")
            )

        # Query for All scripture or Bible: only chapter names + Book ID
        l_query = """
            select
                ID_BOOK
                , N_CHAPTER_COUNT
                , ST_NAME_EN
                , ST_NAME_FR
            from TB_BOOK
            where {0}
            order by ID_GROUP_0, N_ORDER
            ;""".format(
            l_cond
        )

    g_loggerSE3.debug("l_query: {0}".format(l_query))
    try:
        l_cursor = l_dbConnection.cursor(buffered=True)
        l_cursor.execute(l_query)

        # Quran only (2 columns with Surah names)
        if p_context["K"][0:2] == "Ta":
            # title for Quran (depending on Surah order)
            l_response += '<h1 class="TocTitle">{0}</h1><div class="QuranToc"><div class="QuranTocCol1">\n'.format(
                se3_utilities.get_user_string(p_context, "m_tocQuranTitle")
                if p_context["K"] == "Ta1"
                else se3_utilities.get_user_string(p_context, "m_tocQuranTitleRev")
            )

            l_chapterCount = 1
            for l_chapter, l_nameOr, l_nameOr2, l_nameEn, l_nameFr in l_cursor:

                l_tocLink = se3_utilities.makeLinkCommon(
                    p_context, "Qur", l_chapter, "1", l_chapter, p_command="P", p_class="TocLink", p_v2="x"
                )

                l_response += ('<p class="QuranSurah">' + l_tocLink + ": {0} - {1}</p>\n").format(
                    l_nameFr if p_context["z"] == "fr" else l_nameEn, l_nameOr2
                )

                # column break 1-57 / 58-114
                if l_chapterCount == 57:
                    l_response += '</div><div class="QuranTocCol2">\n'

                l_chapterCount += 1

            l_response += "</div></div>\n"
        # Bible & All scripture (Book name + list of chapter numbers)
        else:
            for l_bookId, l_chapterCount, l_nameEn, l_nameFr in l_cursor:

                l_chapLinks = " ".join(
                    [
                        se3_utilities.makeLinkCommon(
                            p_context, l_bookId, i, "1", i, p_command="P", p_class="TocLink", p_v2="x"
                        )
                        for i in range(1, l_chapterCount + 1)
                    ]
                )

                l_response += '<p class="TocBook">{0}: {1}</p>\n'.format(
                    l_nameFr if p_context["z"] == "fr" else l_nameEn, l_chapLinks
                )

        l_cursor.close()

    except Exception as l_exception:
        g_loggerSE3.warning("Something went wrong {0}".format(l_exception.args))

    p_dbConnectionPool.releaseConnection(l_dbConnection)

    return l_response, p_context, ec_app_params.g_appTitle
def internal_get_header_controls(p_context):
    # number of version selection checkboxes per column
    l_segmentLength = 10
    # Max number of versions to display in the status display
    l_selectedLimit = 4

    # Bible version list for the status display (beginning)
    l_statusDisplay = "<b>{0}</b>: ".format(se3_utilities.get_user_string(p_context, "m_bible"))

    # Bible versions selection checkboxes (beginning)
    l_bibleVersionControl = '<div class="VersionSegment">' + '<div class="VersionSelector"><b>{0}</b>:</div>'.format(
        se3_utilities.get_user_string(p_context, "m_bibleVersions")
    )

    # produce both the status display Bible version list and the Bible version selection checkbox block
    l_segmentCount = 1
    l_verMask = 1
    l_selectedCount = 0
    l_selectedList = [v[0] for v in se3_utilities.get_version_list(p_context, False, "B")]
    for l_versionId, l_language, l_default, l_labelShort, l_labelTiny, l_basmalat in se3_utilities.getVersionList("B"):
        # Bible selection checkboxes
        # Each checkbox row is enclosed in a <div class="VersionSelector"> together with its label
        # The checkbox format is:
        #
        # <input type="checkbox" value="" class="ToggleVersion" name="" ver_mask="xx" bible_quran="B" yy>
        #
        # xx = hexadecimal bit mask indicating the version
        # yy = 'checked' if version selected or nothing otherwise
        l_bibleVersionControl += (
            '<div class="VersionSelector">'
            + '<input type="checkbox" value="" '
            + 'class="ToggleVersion ToggleVersionBible" name="" ver_mask="{2}" '
            + 'bible_quran="B" {1}>&nbsp{0}</div>\n'
        ).format(l_labelShort, "checked" if l_versionId in l_selectedList else "", l_verMask)

        # status display Bible version list
        if l_versionId in l_selectedList and l_selectedCount < l_selectedLimit:
            l_statusDisplay += l_labelTiny + ", "
            l_selectedCount += 1

        l_segmentCount += 1
        l_verMask *= 2
        # column break if column height reached
        if l_segmentCount % l_segmentLength == 0:
            l_segmentCount = 0
            l_bibleVersionControl += '</div><div class="VersionSegment">'

    l_statusDisplay = re.sub(",\s$", "", l_statusDisplay)
    # adding ... at the end of the status display if there are more Bible versions than the limit
    if len(l_selectedList) > l_selectedLimit:
        l_statusDisplay += ", ... "
    else:
        l_statusDisplay += " "

    l_bibleVersionControl += ' <input type="button" id="UnselectAllBible" value="{0}"></div>\n'.format(
        se3_utilities.get_user_string(p_context, "m_unselectAll")
    )
    l_bibleVersionControl = re.sub('<div class="VersionSegment"></div>$', "", l_bibleVersionControl)

    # Quran versions selection checkboxes (beginning)
    l_quranVersionControl = '<div class="VersionSegment">' + '<div class="VersionSelector"><b>{0}</b>:</div>'.format(
        se3_utilities.get_user_string(p_context, "m_quranVersions")
    )

    # Quran version list for the status display (beginning)
    l_statusDisplay += "<b>{0}</b>: ".format(se3_utilities.get_user_string(p_context, "m_quran"))

    # produce both the status display Quran version list and the Quran version selection checkbox block
    l_segmentCount = 1
    l_verMask = 1
    l_selectedCount = 0
    l_selectedList = [v[0] for v in se3_utilities.get_version_list(p_context, False, "Q")]
    for l_versionId, l_language, l_default, l_labelShort, l_labelTiny, l_basmalat in se3_utilities.getVersionList("Q"):
        # Quran selection checkboxes
        # Each checkbox row is enclosed in a <div class="VersionSelector"> together with its label
        # The checkbox format is:
        #
        # <input type="checkbox" value="" class="ToggleVersion" name="" ver_mask="xx" bible_quran="B" yy>
        #
        # xx = hexadecimal bit mask indicating the version
        # yy = 'checked' if version selected or nothing otherwise
        l_quranVersionControl += (
            '<div class="VersionSelector"><input type="checkbox" value="" '
            + 'class="ToggleVersion ToggleVersionQuran" name="" ver_mask="{2}" '
            + 'bible_quran="Q" {1}>&nbsp{0}</div>\n'
        ).format(l_labelShort, "checked" if l_versionId in l_selectedList else "", l_verMask)

        # status display Quran version list
        if l_versionId in l_selectedList and l_selectedCount < l_selectedLimit:
            l_statusDisplay += l_labelTiny + ", "
            l_selectedCount += 1

        l_segmentCount += 1
        l_verMask *= 2
        # column break if column height reached
        if l_segmentCount % l_segmentLength == 0:
            l_segmentCount = 0
            l_quranVersionControl += '</div><div class="VersionSegment">'

    l_statusDisplay = re.sub(",\s$", "", l_statusDisplay)
    # adding ... at the end of the status display if there are more Quran versions than the limit
    if len(l_selectedList) > l_selectedLimit:
        l_statusDisplay += ", ... "

    l_quranVersionControl += ' <input type="button" id="UnselectAllQuran" value="{0}"></div>\n'.format(
        se3_utilities.get_user_string(p_context, "m_unselectAll")
    )
    l_quranVersionControl = re.sub('<div class="VersionSegment"></div>$', "", l_quranVersionControl)

    # parameter checkboxes (same formatting as version checkboxes)
    l_paramControl = '<div class="VersionSegment">' + '<div class="VersionSelector"><b>{0}</b>:</div>'.format(
        se3_utilities.get_user_string(p_context, "m_paramControl")
    )

    # list of tuples used to feed the loop below. Contains all the necessary elements for each parameter checkbox
    l_tmpList = [
        # the substitution is because some labels have '·' instead of ' ' in order to separate words
        (se3_utilities.get_user_string(p_context, "sv_AllVersions"), p_context["a"], se3_utilities.g_svAllVersions),
        (se3_utilities.get_user_string(p_context, "m_DisplayLxx"), p_context["x"], se3_utilities.g_svDisplayLxx),
        (se3_utilities.get_user_string(p_context, "m_DisplayNasb"), p_context["n"], se3_utilities.g_svDisplayNasb),
        (se3_utilities.get_user_string(p_context, "m_DisplayKJV"), p_context["k"], se3_utilities.g_svDisplayKjv),
        (se3_utilities.get_user_string(p_context, "p_displayGround"), p_context["g"], se3_utilities.g_pDisplayGround),
        (se3_utilities.get_user_string(p_context, "p_parallelVersions"), p_context["r"], se3_utilities.g_pParallel),
    ]

    for l_label, l_condition, l_mask in l_tmpList:
        l_paramControl += (
            '<div class="VersionSelector"><input type="checkbox"  value="" '
            + 'class="ToggleParameter" name="" param_mask="{2}" '
            + "{1}>&nbsp{0}</div>\n"
        ).format(
            # the substitution is because some labels have '·' instead of ' ' in order to separate words
            re.sub("·", " ", l_label),
            "checked" if l_condition else "",
            l_mask,
        )

    l_paramControl += "</div>"

    return l_bibleVersionControl, l_quranVersionControl, l_paramControl, l_statusDisplay
def internal_get_labels(p_context):
    l_substituteVar = dict()

    # Search form labels and current values
    l_substituteVar["label_search"] = se3_utilities.get_user_string(p_context, "m_labelSearch")
    l_substituteVar["label_wholeWords"] = se3_utilities.get_user_string(p_context, "m_labelWholeWords")
    l_substituteVar["label_caseSensitive"] = se3_utilities.get_user_string(p_context, "m_labelCaseSensitive")
    l_substituteVar["label_exclude"] = se3_utilities.get_user_string(p_context, "m_labelExclude")
    l_substituteVar["label_searchScope"] = se3_utilities.get_user_string(p_context, "m_labelSearchScope")

    # Search mode value labels
    l_substituteVar["label_searchMode"] = se3_utilities.get_user_string(p_context, "m_labelSearchMode")
    l_substituteVar["label_searchMode0"] = se3_utilities.get_user_string(p_context, "m_labelSearchMode0")
    l_substituteVar["label_searchMode1"] = se3_utilities.get_user_string(p_context, "m_labelSearchMode1")
    l_substituteVar["label_searchMode2"] = se3_utilities.get_user_string(p_context, "m_labelSearchMode2")

    # Search mode current value
    l_substituteVar["inputValue_e0"] = ""
    l_substituteVar["inputValue_e1"] = ""
    l_substituteVar["inputValue_e2"] = ""
    l_substituteVar["inputValue_e" + p_context["e"]] = "selected"

    # Quran scope value labels
    l_substituteVar["label_searchScopeQ"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeQ")
    l_substituteVar["label_searchScopeQ0"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeQ0")
    l_substituteVar["label_searchScopeQ1"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeQ1")

    # Quran scope current value
    l_substituteVar["inputValue_h0"] = ""
    l_substituteVar["inputValue_h1"] = ""
    l_substituteVar["inputValue_h" + p_context["h"]] = "selected"

    # NT scope value labels
    l_substituteVar["label_searchScopeNT"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeNT")
    l_substituteVar["label_searchScopeNT0"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeNT0")
    l_substituteVar["label_searchScopeNT1"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeNT1")
    l_substituteVar["label_searchScopeNT2"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeNT2")
    l_substituteVar["label_searchScopeNT3"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeNT3")
    l_substituteVar["label_searchScopeNT4"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeNT4")

    # NT scope current value
    l_substituteVar["inputValue_i0"] = ""
    l_substituteVar["inputValue_i1"] = ""
    l_substituteVar["inputValue_i2"] = ""
    l_substituteVar["inputValue_i3"] = ""
    l_substituteVar["inputValue_i4"] = ""
    l_substituteVar["inputValue_i" + p_context["i"]] = "selected"

    # OT scope value labels
    l_substituteVar["label_searchScopeOT"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeOT")
    l_substituteVar["label_searchScopeOT0"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeOT0")
    l_substituteVar["label_searchScopeOT1"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeOT1")
    l_substituteVar["label_searchScopeOT2"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeOT2")
    l_substituteVar["label_searchScopeOT3"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeOT3")
    l_substituteVar["label_searchScopeOT4"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeOT4")
    l_substituteVar["label_searchScopeOT5"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeOT5")

    # OT scope current value
    l_substituteVar["inputValue_j0"] = ""
    l_substituteVar["inputValue_j1"] = ""
    l_substituteVar["inputValue_j2"] = ""
    l_substituteVar["inputValue_j3"] = ""
    l_substituteVar["inputValue_j4"] = ""
    l_substituteVar["inputValue_j5"] = ""
    l_substituteVar["inputValue_j" + p_context["j"]] = "selected"

    # TOC labels
    l_substituteVar["toc_allScripture"] = se3_utilities.get_user_string(p_context, "m_tocAllScripture")
    l_substituteVar["toc_Quran"] = se3_utilities.get_user_string(p_context, "m_quran")
    l_substituteVar["toc_QuranRev"] = se3_utilities.get_user_string(p_context, "m_tocQuranRev")
    l_substituteVar["toc_NT"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeNT")
    l_substituteVar["toc_OT"] = se3_utilities.get_user_string(p_context, "m_labelSearchScopeOT")
    l_substituteVar["toc_toc"] = se3_utilities.get_user_string(p_context, "m_tocToc")

    # Lexicon labels
    l_substituteVar["lex_Arabic"] = se3_utilities.get_user_string(p_context, "m_lexArabic")
    l_substituteVar["lex_Greek"] = se3_utilities.get_user_string(p_context, "m_lexGreek")
    l_substituteVar["lex_Hebrew"] = se3_utilities.get_user_string(p_context, "m_lexHebrew")
    l_substituteVar["lex_lex"] = se3_utilities.get_user_string(p_context, "m_lexLex")

    # Apply button label
    l_substituteVar["ApplyLabel"] = se3_utilities.get_user_string(p_context, "m_ApplyLabel")

    # Left panel section collapse buttons in open and closed positions
    l_substituteVar["CollapsarShow"] = se3_utilities.get_user_string(p_context, "m_CollapsarShow")
    l_substituteVar["CollapsarHide"] = se3_utilities.get_user_string(p_context, "m_CollapsarHide")

    return l_substituteVar