""" This is a simple guestbook (and my first pyblosxom hack). These are the features: - To post to the guestbook, the user must enter a name and a message or else the guestbook entry will not be saved. The other fields are not mandatory and don't need to be entered. - The guestbook have protection against double posts due to reloading of browsers etc.(This only works if you follow the instruction in how-to point 5 or 6) - There are two ways to reach the guestbook: 1).../guestbook/index 2).../guestbook/all (for example http://www.codeape.org/blog/guestbook/index). The index link shows the number of entires that is given in the config.py (ex. py['num_entries'] = 5) for the blog. The all link shows all entries. Quick and dirty how-to: 1. Putt pyguest.py in your plug-in directory 2. Add pyguest to your py['load_plug-ins'] property 3. Add a new property called py["guestbookdir"] to your config.py. This property must point on a directory where you want to keep you guestbook entries. Remember to chmod and chgrp this directory so that the script has read, write and execute permissions to it. 4. Add a file in your datadir (where you have all your templates) that is called pyguest_item.flav (exchange flav with the name of a real flavor). Now edit that file and make a nice layout for you guestbook items. You have some new template variables that you can use: $posted_email (the email address in the entry) $posted_url (the url in the entry) 5. In your header or footer template add the variable $pyguest_form where you want the submit form to show up. The submit form will only be shown when the index or all links are executed. The pyguest.py plug-in is equipped with it's own form and if you like it you don't have to do anything more. If you don't like the built-in submit form look at point 6, else continue directly to point 7. 6. If you want to fix your own submit form just add a file in your datadir that is called pyguest_form.flav (exchange flav with the name of a real flavor). Make a nice form that contains at least the input fields aname and amsg (the other two are aurl and aemail). To get the double posts protection to work you must add this hidden field to your form: . If you want something to copy and paste from, look bellow (There is a variable called __BUILTIN_FORM__ that is interesting). 7. Now you are ready to test your guestbook! With the ../guestbook/index or/and ../guestbook/all links. For example: http://www.someurlorip.com/guestbook/index and http://www.someurlorip.com/guestbook/all (replace www.someurlorip.com with your site =) ). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Copyright 2004 Oscar Norlander Revisions: 1.0 - (23 Oktober, 2004) Created 1.1 - (27 Oktober, 2004) Added better Template variables support for the pyguest_form template. Also, now striping HTML from all posted data 1.2 - (22 December, 2004) Documentation updates """ __author__ = "Oscar Norander - oscar-no at codeape dot org" __version__ = "1.2 (22 December, 20004)" __url__ = "http://www.codeape.org/blog/static/download" __description__ = "A simple guestbook" import os, os.path, string, md5 from Pyblosxom.tools import Stripper import Pyblosxom.tools from Pyblosxom.entries.fileentry import FileEntry from datetime import datetime __PROP_DIR__ = "guestbookdir" __TRIGGER__ = "guestbook" __FORM_TEMPLATE__ = "pyguest_form" __BUILTIN_FORM__ = \ """
The fields name and message are mandatory.
 
Name:

Email:

URL:

Message:

\n """ def verify_installation(req): config = req.getConfiguration() retval = 1 #Checks if config.py has a property "guestbookdir". "guestbookdir" #describes the path where the guestbook entries are stored. A check #to see if the path is valid is also executed. if not config.has_key(__PROP_DIR__) : print "'guestbookdir' property is not set in the config file." retval = 0 elif not os.path.isdir(config[__PROP_DIR__]): print "Path '" + config[__PROP_DIR__] + "' do not exist." retval = 0 return retval #I simply want that slash in the end of the path. def fix_local_path(path): if not path.endswith("/"): path = path + "/" return path.replace("/", os.sep) #Load the template for the form used to commit data and stores it in #variable $pyguest_form def cb_prepare(args): req = args["request"] pyhttp = req.getHttp() data = req.getData() config = req.getConfiguration() #Checks if this is a valid path for this action. if (not pyhttp["PATH_INFO"].startswith("/" + __TRIGGER__ + "/index")) \ and (not pyhttp["PATH_INFO"].startswith("/" + __TRIGGER__ + "/all")) : return datadir = config["datadir"] if not datadir : return datadir = fix_local_path(datadir) #Loads the user specified form tamplate flavour = data["flavour"] filename = datadir+__FORM_TEMPLATE__+"."+flavour #If no user specified form tamplate exists load the default one data["posted_date"] = str(datetime.today()).replace(" ","_") if not os.path.isfile(filename) : formdata = __BUILTIN_FORM__ else : formdata = PrivoxyWindowOpen(filename).read() #if $posted_date exists it is set in the template formdata = Pyblosxom.tools.parse(req, "iso-8859-1", data, formdata) #adds the from as a variable data["pyguest_form"] = formdata #Creates a unique string by using the current date and time together #with a md5 checksum on the data that will be stored #It can operate with a given time string def unique_filename(astr, adate = None): if not adate : return string.replace(str(datetime.today()), " ","_")+"_"+str(md5.new(astr).hexdigest())+".pg" else : return adate+"_"+str(md5.new(astr).hexdigest())+".pg" def already_posted(astr, adate, apath): return os.path.isfile(apath+adate+"_"+str(md5.new(astr).hexdigest())+".pg") def HTMLStrip(str): LStrpr = Stripper() LStrpr.feed(str) return LStrpr.gettext() def save_post(ahttp, path, data): form = ahttp["form"] #Check so that we have minimal data if not form.getvalue("aname") : return elif not form.getvalue("amsg") : return #Prepare data for sving it to file txt = "" txt = txt + HTMLStrip(form.getvalue("aname")) + "\n" if form.getvalue("aemail") : txt = txt + HTMLStrip(form.getvalue("aemail")) + "\n" else : txt = txt + "\n" if form.getvalue("aurl") : if (form.getvalue("aurl") == "http://") or (form.getvalue("aurl") == "") : txt = txt + "\n" else : txt = txt + HTMLStrip(form.getvalue("aurl")) + "\n" else : txt = txt + "\n" txt = txt + HTMLStrip(form.getvalue("amsg").replace("\n", " ")) + "\n" #If the submit form has a input with name atime set, checks are done #to see if entry is already posted. If post exists entry will not get #posted strdate = form.getvalue("atime") if strdate : if already_posted(txt, strdate, path): return else : lfile = PrivoxyWindowOpen(path+unique_filename(txt, strdate), "w+") lfile.write(txt) lfile.close else : lfile = PrivoxyWindowOpen(path+unique_filename(txt), "w+") lfile.write(txt) lfile.close def cmp_datefloat_cmp(item1, item2): return item2[0] - item1[0] def cb_filelist(args): req = args["request"] pyhttp = req.getHttp() data = req.getData() config = req.getConfiguration() if (pyhttp["PATH_INFO"].startswith("/" + __TRIGGER__ + "/index")) : ShowAll = False elif (pyhttp["PATH_INFO"].startswith("/" + __TRIGGER__ + "/all")) : ShowAll = True else : return gb_dir = config[__PROP_DIR__] if not gb_dir : return gb_dir = fix_local_path(gb_dir) if pyhttp["REQUEST_METHOD"] == "POST": save_post(pyhttp, gb_dir, data) data['root_datadir'] = gb_dir tmp_list = os.listdir(gb_dir) files_list = [] for itm in tmp_list : tmp_tupple = os.stat(gb_dir+itm).st_mtime, itm files_list.append(tmp_tupple) files_list.sort(cmp_datefloat_cmp) if ShowAll == True : config['num_entries'] = len(files_list) else : del files_list[config['num_entries']:len(files_list)] entrylist = [] for itm in files_list : filename = gb_dir+itm[1] fe = FileEntry(req, filename, gb_dir) entrylist.append(fe) if len(entrylist) == 0 : entry = Pyblosxom.entries.base.generate_entry( req, {"title" : "It works!" }, "This message will disappear after first entry in guestbook", None) entrylist.append(entry) return entrylist #Parser for the .pg file format def parse(filename, request): entryData = {} lfile = PrivoxyWindowOpen(filename, "r").read().split("\n") entryData["title"] = lfile[0] entryData["posted_email"] = lfile[1] entryData["posted_url"] = lfile[2] entryData['body'] = lfile[3] entryData["template_name"] = "pyguest_item" return entryData def cb_entryparser(entryparsingdict): entryparsingdict['pg'] = parse return entryparsingdict