From 66680851f245bd61803c845eb8f17f840161631b Mon Sep 17 00:00:00 2001 From: Serge Noiraud Date: Sat, 13 Feb 2021 17:39:03 +0100 Subject: [PATCH] Narweb: add php session_start (#1169) * Narweb: add php session_start Fixes #12135 - remove php3 - remove duplicate code * libhtml: better pylint score --- gramps/plugins/lib/libhtml.py | 270 ++++++++++++----------- gramps/plugins/webreport/basepage.py | 16 +- gramps/plugins/webreport/calendar.py | 5 +- gramps/plugins/webreport/common.py | 2 +- gramps/plugins/webreport/narrativeweb.py | 33 ++- 5 files changed, 181 insertions(+), 145 deletions(-) diff --git a/gramps/plugins/lib/libhtml.py b/gramps/plugins/lib/libhtml.py index 34d90a986..cfb0cafd4 100644 --- a/gramps/plugins/lib/libhtml.py +++ b/gramps/plugins/lib/libhtml.py @@ -30,7 +30,6 @@ This module exports the Html class #------------------------------------------------------------------------ # Python modules #------------------------------------------------------------------------ -import re #------------------------------------------------------------------------ # @@ -114,10 +113,10 @@ class Html(list): """ Build and return an XML declaration statement - :type version: decimal number - :param version: version of XML to be used. Defaults to 1.0 - :type encoding: string - :param encoding: encoding method to be used. Defaults to "UTF-8" + :type version: decimal number + :param version: version of XML to be used. Defaults to 1.0 + :type encoding: string + :param encoding: encoding method to be used. Defaults to "UTF-8" :type standalone: string :param standalone: "yes" or "no". Defaults to "no" """ @@ -132,16 +131,16 @@ class Html(list): """ Build and return a DOCTYPE statement - :type name: string - :param name: name of this DOCTYPE. Defaults to "html" - :type public: string - :param public: class of this DOCTYPE. Defaults to 'PUBLIC + :type name: string + :param name: name of this DOCTYPE. Defaults to "html" + :type public: string + :param public: class of this DOCTYPE. Defaults to 'PUBLIC :type external_id: string :param external_id: external identifier of this DOCTYPE. Defaults to XHTML 1.0 STRICT - :type args: object - :param args: 0 or more positional parameters to be added to this - DOCTYPE. + :type args: object + :param args: 0 or more positional parameters to be added to + this DOCTYPE. """ return ( '' # @staticmethod - def html(xmlns=_XMLNS, lang='en', *args, **keywargs): + def html(xmlns=_XMLNS, lang='en', php_session=None, *args, **keywargs): """ Build and return a properly-formated object :type xmlns: string - :param xmlns: XML namespace string. Default = 'http://www.w3.org/1999/xhtml' - :type lang: string - :param lang: language to be used. Defaul = 'en' - :rtype: reference to new Html instance - :returns: reference to the newly-created Html instances for object + :param xmlns: XML namespace string. + Default = 'http://www.w3.org/1999/xhtml' + :type lang: string + :param lang: language to be used. Defaul = 'en' + :rtype: reference to new Html instance + :php_session: If we need to have a php session start + :returns: reference to the newly-created Html instances + for object """ - return Html('html', - indent=False, - xmlns=xmlns, - attr='xml:lang="%s" lang="%s"' % ((lang,)*2), - *args, **keywargs - ) + return Html('html', indent=False, xmlns=xmlns, + attr='xml:lang="%s" lang="%s"' % ((lang,)*2), + php=php_session, + *args, **keywargs) # @staticmethod def head(title=None, encoding='utf-8', html5=True, *args, **keywargs): """ Build and return a properly-formated object - :type title: string or None - :param title: title for HTML page. Default=None. If None no - title tag is written + :type title: string or None + :param title: title for HTML page. Default=None. If None no + title tag is written :type encoding: string :param encoding: encoding to be used. Default = 'utf-8' - :param html5: generate html5 syntax. Default = True. Set to False - if pre-html5 syntax required - :rtype: reference to new Html instance - :returns: reference to the newly-created Html instances for object + :param html5: generate html5 syntax. Default = True. Set to False + if pre-html5 syntax required + :rtype: reference to new Html instance + :returns: reference to the newly-created Html instances + for object """ head = Html('head', *args, **keywargs) @@ -199,39 +200,38 @@ class Html(list): return head # @staticmethod - def page(title=None, encoding='utf-8', lang='en', html5=True, cms=False, *args, **keywargs): + def page(title=None, encoding='utf-8', lang='en', html5=True, cms=False, + php_session=None, *args, **keywargs): """ This function prepares a new Html class based page and returns - :type title: string - :param title: title for HTML page. Default=None + :type title: string + :param title: title for HTML page. Default=None :type encoding: string :param encoding: encoding to be used. Default = 'utf-8' - :type lang: string - :param lang: language to be used. Defaul = 'en' - :param html5: generate html5 syntax. Default = True. Set to False - if pre-html5 syntax required - :rtype: three object references - :returns: references to the newly-created Html instances for - page, head and body + :type lang: string + :param lang: language to be used. Defaul = 'en' + :param html5: generate html5 syntax. Default = True. Set to False + if pre-html5 syntax required + :rtype: three object references + :php_session: the note to include before all html code + :returns: references to the newly-created Html instances for + page, head and body """ - page = Html.html(lang=lang, *args, **keywargs) + page = Html.html(lang=lang, php_session=php_session, + *args, **keywargs) if html5: page.addDOCTYPE(external_id=_HTML5) else: page.addXML(encoding=encoding) page.addDOCTYPE(external_id=_XHTML10_STRICT) # - head = Html.head(title=title, - encoding=encoding, - lang=lang, - html5=html5, - indent=False, - *args, **keywargs - ) + head = Html.head(title=title, encoding=encoding, lang=lang, + html5=html5, indent=False, *args, **keywargs) # if cms: - body = Html('div', class_ = "body", indent=False, *args, **keywargs) + body = Html('div', class_="body", indent=False, + *args, **keywargs) else: body = Html('body', indent=False, *args, **keywargs) page += (head, body) @@ -241,34 +241,37 @@ class Html(list): """ Class Constructor: Returns a new instance of the Html class - :type tag: string - :param tag: The HTML tag. Default is 'html' - :type args: optional positional parameters - :param args: 0 more positional arguments to be inserted between - opening and closing HTML tags. - :type indent: boolean or None - :param indent: True ==> indent this object with respect to its parent - False ==> do not indent this object - None ==> no indent for this object (use eg for pre tag) - Defaults to True - :type inline: boolean - :param inline: True ==> instructs the write() method to output this - object and any child objects as a single string - False ==> output this object and its contents one string - at a time - Defaults to False - :type close: boolean or None - :param close: True ==> this tag should be closed normally - e.g. ... - False ==> this tag should be automatically closed - e.g. - None ==> do not provide any closing for this tag + :type tag: string + :param tag: The HTML tag. Default is 'html' + :type args: optional positional parameters + :param args: 0 more positional arguments to be inserted between + opening and closing HTML tags. + :type indent: boolean or None + :param indent: True ==> indent this object with respect to its + parent + False ==> do not indent this object + None ==> no indent for this object + (use eg for pre tag) + Defaults to True + :type inline: boolean + :param inline: True ==> instructs the write() method to output + this object and any child objects as a + single string + False ==> output this object and its contents one + string at a time + Defaults to False + :type close: boolean or None + :param close: True ==> this tag should be closed normally + e.g. ... + False ==> this tag should be automatically closed + e.g. + None ==> do not provide any closing for this tag :type keywargs: optional keyword parameters :param keywargs: 0 or more keyword=argument pairs that should be copied into the opening tag as keyword="argument" attributes - :rtype: object reference - :returns: reference to the newly-created Html instance + :rtype: object reference + :returns: reference to the newly-created Html instance For full usage of the Html class with examples, please see the wiki page at: http://www.gramps-project.org/wiki/index.php?title=Libhtml @@ -284,16 +287,19 @@ class Html(list): # Keywords we don't recognize are saved for later # addition to the opening tag as attributes. # + phpnote = None for keyw, arg in sorted(keywargs.items()): if (keyw in ['indent', 'close', 'inline'] and - arg in [True, False, None]): + arg in [True, False, None]): setattr(self, keyw, arg) - elif keyw == 'attr': # pass attributes along + elif keyw == 'attr': # pass attributes along attr += ' ' + arg - elif keyw[-1] == '_': # avoid Python conflicts - attr += ' %s="%s"' % (keyw[:-1], arg) # pass keyword arg along + elif keyw == 'php': # php init session + phpnote = arg + elif keyw[-1] == '_': # avoid Python conflicts + attr += ' %s="%s"' % (keyw[:-1], arg) # pass keyword arg along else: - attr += ' %s="%s"' % (keyw, arg) # pass keyword arg along + attr += ' %s="%s"' % (keyw, arg) # pass keyword arg along # if tag[0] == '<': # if caller provided preformatted tag? self[0:] = [tag] # add it in @@ -301,7 +307,13 @@ class Html(list): else: if tag in _START_CLOSE: # if tag in special list self.close = False # it needs no closing tag - begin = '<%s%s%s>' % ( # build opening tag with attributes + if phpnote: + # We need to insert php code before the html tag + # This is used to initiate a php session. + htmlhead = phpnote + '<%s%s%s>' + else: + htmlhead = '<%s%s%s>' + begin = htmlhead % ( # build opening tag with attributes tag, attr, ('' if self.close is not False else ' /') @@ -310,7 +322,7 @@ class Html(list): # Use slice syntax since we don't override slicing self[0:] = [begin] + list(args) # add beginning tag if self.close: # if need closing tab - self[len(self):] = ['' % tag] # add it on the end + self[len(self):] = ['' % tag] # add it on the end # def __add(self, value): """ @@ -320,8 +332,8 @@ class Html(list): :type value: object :param value: object to be added - :rtype: object reference - :returns: reference to object with new value added + :rtype: object reference + :returns: reference to object with new value added """ if (isinstance(value, Html) or not hasattr(value, '__iter__') or isinstance(value, str)): @@ -346,11 +358,11 @@ class Html(list): :type cur_value: object :param cur_value: value of object to be replaced - :type value: object - :param value: replacement value + :type value: object + :param value: replacement value - :rtype: object reference - :returns: reference to object with new value added + :rtype: object reference + :returns: reference to object with new value added """ self[self.index(cur_value)] = value # @@ -360,8 +372,8 @@ class Html(list): :type value: object :param value: object to be removed - :rtype: object reference - :returns: reference to object with value removed + :rtype: object reference + :returns: reference to object with value removed """ del self[self.index(value)] return self @@ -372,7 +384,7 @@ class Html(list): """ Returns string representation - :rtype: string + :rtype: string :returns: string representation of object """ return '%s'*len(self) % tuple(self[:]) @@ -382,9 +394,9 @@ class Html(list): Iterator function: returns a generator that performs an insertion-order tree traversal and yields each item found. """ - for item in self[:]: # loop through all list elements + for item in self[:]: # loop through all list elements if isinstance(item, Html): # if nested list found - for sub_item in item: # recurse + for sub_item in item: # recurse yield sub_item else: yield item @@ -393,26 +405,26 @@ class Html(list): # def write(self, method=print, indent='\t', tabs=''): """ - Output function: performs an insertion-order tree traversal - and calls supplied method for each item found. + Output function: performs an insertion-order tree traversal and + calls supplied method for each item found. - :type method: function reference - :param method: function to call with each item found - :type indent: string - :param indenf: string to use for indentation. Default = '\t' (tab) - :type tabs: string - :param tabs: starting indentation + :type method: function reference + :param method: function to call with each item found + :type indent: string + :param indenf: string to use for indentation. Default = '\t' (tab) + :type tabs: string + :param tabs: starting indentation """ if self.indent is None: tabs = '' elif self.indent: tabs += indent - if self.inline: # if inline, write all list and - method(str('%s%s' % (tabs, self))) # nested list elements + if self.inline: # if inline, write all list and + method(str('%s%s' % (tabs, self))) # nested list elements # else: - for item in self[:]: # else write one at a time - if isinstance(item, Html): # recurse if nested Html class + for item in self[:]: # else write one at a time + if isinstance(item, Html): # recurse if nested Html class item.write(method=method, indent=indent, tabs=tabs) else: method(str('%s%s' % (tabs, item))) # else write the line @@ -421,10 +433,10 @@ class Html(list): """ Add an XML statement to the start of the list for this object - :type version: decimal number - :param version: version of XML to be used. Defaults to 1.0 - :type encoding: string - :param encoding: encoding method to be used. Defaults to "UTF-8" + :type version: decimal number + :param version: version of XML to be used. Defaults to 1.0 + :type encoding: string + :param encoding: encoding method to be used. Defaults to "UTF-8" :type standalone: string :param standalone: "yes" or "no". Defaults to "no" """ @@ -436,30 +448,30 @@ class Html(list): self[0:0] = [xmldecl] # def addDOCTYPE(self, name='html', public='PUBLIC', - external_id=_HTML5, *args): + external_id=_HTML5, *args): """ Add a DOCTYPE statement to the start of the list - :type name: string - :param name: name of this DOCTYPE. Defaults to "html" + :type name: string + :param name: name of this DOCTYPE. Defaults to "html" :type external_id: string :param external_id: external identifier of this DOCTYPE. Defaults to XHTML 1.0 STRICT - :type args: object - :param args: 0 or more positional parameters to be added to this - DOCTYPE. + :type args: object + :param args: 0 or more positional parameters to be added + to this DOCTYPE. """ doctype = ( - '' # Note: DOCTYPE declaration must follow XML declaration - if len(self) and self[0][:6] == '') @@ -496,7 +508,7 @@ class Html(list): """ Returns HTML attributes for this object - :rtype: string + :rtype: string :returns: HTML attributes """ attr = self[0].strip('').split(None, 1) @@ -520,20 +532,16 @@ class Html(list): """ Removes HTML attributes for this object """ - self[0] = '<' + self.tag + ( - - # Set correct closing delimiter(s) - - ' />' if self.close is False else '>' - ) + self[0] = '<' + self.tag + (# Set correct closing delimiter(s) + ' />' if self.close is False else '>') # - attr = property(__getattr, __setattr, __delattr) + attr = property(__getattr, __setattr, __delattr) # def __getinside(self): """ Returns list of items between opening and closing tags - :rtype: list + :rtype: list :returns: list of items between opening and closing HTML tags """ return self[1:-1] diff --git a/gramps/plugins/webreport/basepage.py b/gramps/plugins/webreport/basepage.py index 99ea45e26..2634776cd 100644 --- a/gramps/plugins/webreport/basepage.py +++ b/gramps/plugins/webreport/basepage.py @@ -1503,6 +1503,16 @@ class BasePage: @param: title -- Is the title of the web page @param: cal -- The number of directories to use """ + # If .php extension and a note selected, add it to the head section. + phpnote = self.report.options['phpnote'] + note = None + if phpnote and self.ext == ".php": + # This is used to give the ability to have a php init session. + # This note must not contains formatting + # and should only contains php code. ie: + # + note = self.r_db.get_note_from_gramps_id(phpnote).get() + # begin each html page... if self.the_lang: xmllang = self.the_lang.replace('_', '-') @@ -1512,11 +1522,11 @@ class BasePage: (html_escape(self.title_str.strip()), html_escape(the_title)), self.report.encoding, - xmllang, cms=self.usecms) + xmllang, cms=self.usecms, php_session=note) # temporary fix for .php parsing error - if self.ext in [".php", ".php3", ".cgi"]: - del page[0] + if self.ext in [".php", ".cgi"]: + del page[0] # remove the "DOCTYPE" directive # Header constants _meta1 = 'name ="viewport" content="width=device-width, ' diff --git a/gramps/plugins/webreport/calendar.py b/gramps/plugins/webreport/calendar.py index 773418008..0d9006e5d 100644 --- a/gramps/plugins/webreport/calendar.py +++ b/gramps/plugins/webreport/calendar.py @@ -57,7 +57,7 @@ from gramps.gen.display.name import displayer as _nd import gramps.plugins.lib.libholiday as libholiday from gramps.plugins.webreport.basepage import BasePage -from gramps.plugins.webreport.common import do_we_have_holidays +from gramps.plugins.webreport.common import (do_we_have_holidays, _WEB_EXT) from gramps.plugins.lib.libhtml import Html #, xml_lang from gramps.gui.pluginmanager import GuiPluginManager @@ -74,9 +74,6 @@ _LOG = logging.getLogger(".WebPage") FULLCLEAR = Html("div", class_="fullclear", inline=True) -# Web page filename extensions -_WEB_EXT = ['.html', '.htm', '.shtml', '.php', '.php3', '.cgi'] - # Calendar stylesheet names _CALENDARSCREEN = 'calendar-screen.css' _CALENDARPRINT = 'calendar-print.css' diff --git a/gramps/plugins/webreport/common.py b/gramps/plugins/webreport/common.py index eb38cc4f4..344921f22 100644 --- a/gramps/plugins/webreport/common.py +++ b/gramps/plugins/webreport/common.py @@ -50,7 +50,7 @@ LOG = logging.getLogger(".NarrativeWeb") # define clear blank line for proper styling FULLCLEAR = Html("div", class_="fullclear", inline=True) # define all possible web page filename extensions -_WEB_EXT = ['.html', '.htm', '.shtml', '.php', '.php3', '.cgi'] +_WEB_EXT = ['.html', '.htm', '.shtml', '.php', '.cgi'] # used to select secured web site or not HTTP = "http://" HTTPS = "https://" diff --git a/gramps/plugins/webreport/narrativeweb.py b/gramps/plugins/webreport/narrativeweb.py index 85e786bac..74976c61e 100644 --- a/gramps/plugins/webreport/narrativeweb.py +++ b/gramps/plugins/webreport/narrativeweb.py @@ -1906,6 +1906,8 @@ class NavWebOptions(MenuReportOptions): self.__toggle = None self.__death_anniv = None self.__after_year = None + self.__ext = None + self.__phpnote = None db_options = name + ' ' + dbase.get_dbname() MenuReportOptions.__init__(self, db_options, dbase) @@ -1929,7 +1931,6 @@ class NavWebOptions(MenuReportOptions): self.__add_translations(menu) self.__add_calendar_options(menu) - def __add_report_options(self, menu): """ Options on the "Report Options" tab. @@ -1999,11 +2000,12 @@ class NavWebOptions(MenuReportOptions): category_name = _("Html options") addopt = partial(menu.add_option, category_name) - ext = EnumeratedListOption(_("File extension"), ".html") + self.__ext = EnumeratedListOption(_("File extension"), ".html") for etype in _WEB_EXT: - ext.add_item(etype, etype) - ext.set_help(_("The extension to be used for the web files")) - addopt("ext", ext) + self.__ext.add_item(etype, etype) + self.__ext.set_help(_("The extension to be used for the web files")) + addopt("ext", self.__ext) + self.__ext.connect("value-changed", self.__ext_changed) cright = EnumeratedListOption(_('Copyright'), 0) for index, copt in enumerate(_COPY_OPTIONS): @@ -2197,13 +2199,22 @@ class NavWebOptions(MenuReportOptions): addopt("contactimg", contactimg) headernote = NoteOption(_('HTML user header')) - headernote.set_help(_("A note to be used as the page header")) + headernote.set_help(_("A note to be used as the page header" + " or a php code to insert.")) addopt("headernote", headernote) footernote = NoteOption(_('HTML user footer')) footernote.set_help(_("A note to be used as the page footer")) addopt("footernote", footernote) + # This option will be available only if you select ".php" in the + # "File extension" from the "Html" tab + self.__phpnote = NoteOption(_('PHP user session')) + self.__phpnote.set_help(_("A note to use for starting the php session." + "\nThis option will be available only if " + "the .php file extension is selected.")) + addopt("phpnote", self.__phpnote) + def __add_images_generation_options(self, menu): """ Options on the "Page Generation" tab. @@ -2602,6 +2613,16 @@ class NavWebOptions(MenuReportOptions): self.__maxupdates.set_available(False) self.__maxdays.set_available(False) + def __ext_changed(self): + """ + The file extension changed. + If .php selected, we must set the PHP user session available + """ + if self.__ext.get_value()[:4] == ".php": + self.__phpnote.set_available(True) + else: + self.__phpnote.set_available(False) + def __usecms_changed(self): """ We need to use cms or not