#!/usr/bin/python # This program is free software. It comes without any warranty, to # the extent permitted by applicable law. You can redistribute it # and/or modify it under the terms of the Do What The Fuck You Want # To Public License, Version 2, as published by Sam Hocevar. See # http://sam.zoy.org/wtfpl/COPYING for more details. # Authors: Stefan Ritter # Adrian Vondendriesch # Description: A simple blogging software import cgi, os, time, glob, re, md5, sys, random, smtplib import ConfigParser def generate_uuid(string): string_md5sum = md5.new(string).hexdigest() string_md5sum_1 = string_md5sum[0:8] string_md5sum_2 = string_md5sum[8:12] string_md5sum_3 = string_md5sum[12:16] string_md5sum_4 = string_md5sum[16:20] string_md5sum_5 = string_md5sum[20:32] string = string_md5sum_1 + '-' + string_md5sum_2 + '-' + string_md5sum_3 + '-' + string_md5sum_4 + '-' + string_md5sum_5 return string def errorpage(string): print 'Content-type: text/html\n' print '' print '' print '' print ' Error!' print '' print '' if string == "entries_dir": print ' Directory "' + entries_dir + '" does not exist!' elif string == "staticpages_dir": print ' Directory "' + staticpages_dir + '" does not exist!' elif string == "linklist": print ' File "linklist" does not exist!' elif string =="not writable entries_dir": print ' Admin is a dumbass!!! Tell him to make his entries_dir writable.' else: print ' ' + string + ' is not set in configuration, please check your installation!' print '' print '' sys.exit() def document_header(string): if string == "xhtml-transitional": print 'Content-type: text/html\n' print '' print '' if string == "xhtml-strict": print 'Content-type: text/html\n' print '' print '' if string == "atom": print 'Content-type: application/atom+xml\n' print '' print '' if string == "rss": print 'Content-type: application/rss+xml\n' print '' print '' configuration = ConfigParser.ConfigParser() configuration.read('configuration') try: blog_title = configuration.get('personal', 'blog_title') except: errorpage("blog_title") try: blog_subtitle = configuration.get('personal', 'blog_subtitle') except: errorpage("blog_subtitle") try: blog_url = configuration.get('personal', 'blog_url') except: errorpage("blog_url") try: keywords = configuration.get('personal', 'keywords') except: errorpage("keywords") try: entries_dir = configuration.get('personal', 'entries_dir') except: errorpage("entries_dir") if not os.path.exists(entries_dir): errorpage("entries_dir") try: entries_suffix = configuration.get('personal', 'entries_suffix') except: errorpage("entries_suffix") try: staticpages_dir = configuration.get('personal', 'staticpages_dir') except: errorpage("staticpages_dir") if not os.path.exists(staticpages_dir): errorpage("staticpages_dir") try: style = configuration.get('look', 'style') except: errorpage("style") try: entries_per_page = configuration.getint('look', 'entries_per_page') except: errorpage("entries_per_page") try: monthlist = configuration.get('look', 'monthlist') except: errorpage("monthlist") try: staticpages = configuration.get('look', 'staticpages') except: errorpage("staticpages") try: linklist = configuration.get('look', 'linklist') except: errorpage("linklist") if not os.path.exists("linklist"): errorpage("linklist") try: permalinks = configuration.get('look', 'permalinks') except: errorpage("permalinks") try: comments = configuration.get('look', 'comments') except: errorpage("comments") try: newest_first = configuration.get('look', 'newest_first') except: errorpage("newest_first") try: new_comment_mail = configuration.get('smtp', 'new_comment_mail') except: errorpage("new_comment_mail") try: mail_to = configuration.get('smtp', 'mail_to') except: errorpage("mail_to") try: smtp_host = configuration.get('smtp', 'smtp_host') except: errorpage("smtp_host") try: smtp_user = configuration.get('smtp', 'smtp_user') except: errorpage("smtp_user") try: smtp_pass = configuration.get('smtp', 'smtp_pass') except: errorpage("smtp_pass") # Read POST Variables action = cgi.FieldStorage() month_display = action.getvalue('m') static_display = action.getvalue('s') if static_display: static_display = re.sub('/', '', static_display) post_display = action.getvalue('p') if post_display: post_display = re.sub(' ', '-', post_display) post_display = re.sub('/', '', post_display) allentries_display = action.getvalue('a') feed_display = action.getvalue('feed') if not month_display: month_display = "" if not post_display: post_display = "" if not static_display: static_display = "" if not allentries_display: allentries_display = "" if not feed_display: feed_display = "" # Commentstuff ctitle = action.getvalue('ctitle') cname = action.getvalue('cname') ctext = action.getvalue('ctext') cquiz = action.getvalue('cquiz') cquizv = action.getvalue('cquizv') if not ctitle: ctitle = "" if not cname: cname = "" if not ctext: ctext = "" if not cquiz: cquiz = "" if not cquizv: cquizv = "" # Comment to commit? if cname and ctext and ctitle: # Prevent XSS hacks cname = cname.replace("<", "<") \ .replace(">", ">") \ .replace("\"", """) ctext = ctext.replace("<", "<") \ .replace(">", ">") \ .replace("\"", """) # Add comment if not cquiz == cquizv: errorpage("Brainmode") else: comments_file = glob.glob(entries_dir + ctitle + '.comments') if not comments_file: try: content = open(entries_dir + ctitle + '.comments', "w") content.close() except: errorpage('not writable entries_dir') comments_file = glob.glob(entries_dir + ctitle + '.comments') try: content = open(comments_file[0], "a+") content.write("-." + cname + "\n") content.write("+." + time.asctime() + "\n") ctext = ctext.split("\n") for line in ctext: content.write("." + line + "\n") content.close() # Send mail? if new_comment_mail: msg = 'From: Blogthon\nTo: ' + mail_to + '\nSubject: New comment on ' + blog_title + '\n\nSomeone wrote a comment to this entry: ' + blog_url + '?p=' + re.sub(' ', '-', ctitle) smtp = smtplib.SMTP(smtp_host) if smtp_user != '' and smtp_pass != '': smtp.login(smtp_user, smtp_pass) smtp.sendmail(blog_title, mail_to, msg) smtp.quit() except: errorpage('commentsfile seems not to be writable!') # Read entries and store their title and timestamp entries = [] entries_list = glob.glob(entries_dir + '*.' + entries_suffix) for entry in entries_list: timestamp = os.stat(entry) timestamp = time.localtime(timestamp[8]) entry = timestamp, entry entries.append(entry) if newest_first: entries.sort(reverse=True) else: entries.sort() # Generate atom feed if feed_display == "atom": title = str(entries[0][1]).replace('entries/', '', 1).replace('.' + entries_suffix, '') date = entries[0][0] blog_title_md5sum = generate_uuid(blog_title) title_md5sum = generate_uuid(title) # Atom need a 2byte string month = str(date[1]) day = str(date[2]) hour = str(date[3]) min = str(date[4]) sec = str(date[5]) if len(str(date[1])) == 1: month = '0' + str(date[1]) if len(str(date[2])) == 1: day = '0' + str(date[2]) if len(str(date[3])) == 1: hour = '0' + str(date[3]) if len(str(date[4])) == 1: min = '0' + str(date[4]) if len(str(date[5])) == 1: sec = '0' + str(date[5]) document_header("atom") print '' print ' ' print ' ' + blog_title + '' print ' ' print ' ' + blog_title + '' print ' urn:uuid:' + blog_title_md5sum + '' print ' ' + str(date[0]) + '-' + month + '-' + day + 'T' + hour + ':' + min + ':' + sec + 'Z' print '' print ' ' print ' ' + title + '' print ' ' print ' urn:uuid:' + title_md5sum + '' print ' ' + str(date[0]) + '-' + month + '-' + day + 'T' + hour + ':' + min + ':' + sec + 'Z' print ' ' print '' # Generate rss 2.0 feed elif feed_display == "rss": title = str(entries[0][1]).replace('entries/', '', 1).replace('.' + entries_suffix, '') date = entries[0][0] blog_title_md5sum = generate_uuid(blog_title) title_md5sum = generate_uuid(title) document_header("rss") print ' ' print ' ' + blog_title + '' print ' ' + blog_url + '' print ' ' + blog_subtitle + '' # TODO: Format like: "Tue, 8 Jul 2008 2:43:19" #print ' ' + date + '' print '' print ' ' print ' ' + title + '' print ' ' + blog_url + '' print ' ' + title_md5sum + '' print ' ' print ' ' print '' # Generate regular page else: document_header("xhtml-strict") # XHTML Header print ' ' print ' ' + blog_title + '' print ' ' print ' ' print ' ' print ' ' print ' ' print ' ' print '' # Site header print '
' print '
' print ' ' + blog_title + '' print '
' print '
' print ' ' + blog_subtitle + '' print '
' print '
' print '' # RSS feed print '
' if os.path.exists('styles/' + style.replace('.css', '') + '_img/rss.jpg'): print ' ' else: print ' rss' print '
' print '' # Atom feed print '
' if os.path.exists('styles/' + style.replace('.css', '') + '_img/atom.jpg'): print ' atom' print '
' print '' # Staticpages if staticpages == "True": staticpages = [] staticpages_list = glob.glob(staticpages_dir + '*') staticpages_list.sort() print '
' print '
pages
' print '
' print '
    ' for staticpage in staticpages_list: title = re.sub('\w+?\/\d+?-', '', staticpage) link = re.sub('\w+?\/', '', staticpage) print '
  • ' + title + '
  • ' print '
' print '
' print ' ' print '
' print '' # Monthlist if monthlist == "True": olddate = "" print '
' print '
months
' print '
' print '
    ' for entry in entries: date = time.strftime("%m%Y", entry[0]) date_display = time.strftime("%h %Y", entry[0]) if not olddate == date: print '
  • ' + date_display + '
  • ' olddate = date print '
' print '
' print ' ' print '
' print '' # Linklist if linklist == "True": print ' ' print '' print '
' print '' # Staticpage if static_display != "": content = open(staticpages_dir + static_display, "r") print '
' print '
' + re.sub('\d+?-', '', static_display) + '
' print '
' print '

' for line in content: if re.search('

  • ', line) or re.search('
      ', line) or re.search('
    ', line) or re.search('
      ', line) or re.search('
    ', line): print ' ' + line.strip() else: print ' ' + line.strip() + '
    ' print '

    ' print '
  • ' print ' ' print '
    ' print '
    ' print '
    ' print '
    ' print '
    ' print '' content.close() # Entry else: entry_counter = 0 for entry in entries: date = time.strftime("%c", entry[0]) date_to_compare = time.strftime("%m%Y", entry[0]) # Needed for permalinks entry = entry[1] title = entry.replace('entries/', '', 1) title = title.replace('.' + entries_suffix, '') if month_display == date_to_compare or not month_display: if post_display == re.sub(' ', '-', title) or not post_display: if allentries_display == "1" or entry_counter < entries_per_page: content = open(entry, "r") print '
    ' if permalinks: print '
    ' + title + '
    ' else: print '
    ' + title + '
    ' print ' ' print '
    ' for line in content: if re.search('
  • ', line) or re.search('
      ', line) or re.search('
    ', line) or re.search('
      ', line) or re.search('
    ', line): print ' ' + line.strip() else: print ' ' + line.strip() + '
    ' print '
  • ' print ' ' print '
    ' print '
    ' print '
    ' print '
    ' # Comments... # ... are shown when post_display and comments_file isn't false comments_file = glob.glob(entries_dir + title + '.comments') if post_display: if comments_file: comments_file = glob.glob(entries_dir + title + '.comments') comments_content = open(comments_file[0], "r") print '
    ' print '
    ' print '' print '
    ' notfirstline = 0 # Ugly fix for closing comment containers for line in comments_content: if re.search("^-", line): if notfirstline == 1: print '
    ' print ' ' notfirstline = 0; print '
    ' print '
    ' + line.split(".", 1)[1].strip() + '
    ' elif re.search("^\+", line): print '
    ' + line.split(".", 1)[1].strip() + '
    ' print '
    ' else: notfirstline = 1; line = line.split(".", 1)[1] print ' ' + line.strip() + '
    ' print '' print '
    ' print '
    ' comments_content.close() else: print ' ' print ' ' print '
    ' # Form for adding comments random_int_a = random.randint(1,9) random_int_b = random.randint(1,9) cquizv = random_int_a + random_int_b print '
    ' print '
    ' print ' ' print ' ' print ' ' print '
    ' print '
    ' print '
    ' print '
    ' print '
    ' print '
    ' print '' if comments == "True": comments_file = glob.glob(entries_dir + title + '.comments') if not comments_file and not post_display: print '
    ' print ' no comments' print '
    ' print '
    ' print '' elif comments_file and not post_display: comments_content = open(comments_file[0], "r") comments_counter = 0 for line in comments_content: if line.split(".", 1)[0] == "-": comments_counter += 1 print '
    ' print ' comments (' + str(comments_counter) + ')' print '
    ' print ' ' print '' comments_content.close() else: print ' ' print '' content.close() entry_counter += 1 if not month_display and not post_display and not allentries_display and entry_counter == entries_per_page: # Display pagelist print '
    View all entries...
    ' print ' ' print '' print ' ' print '' # vim: set tw=0 ts=4: