#!/usr/bin/python

import os
import sys
import cgi
import types
import string
import MySQLdb
import time

import md5
import sha

# In-browser debugging.
import cgitb
cgitb.enable()

form = cgi.FieldStorage()

print "Content-type: text/html\n"
print "\n"

# For debugging only.
# cgi.print_environ()

class AndThenSum:
  """Return a generic checksumming object to compute different types
  of checksums (MD5 and SHA1) for the same data."""
  def __init__(self):
    self.md5sum = md5.new()
    self.sha1sum = sha.new()
  def update(self, buf):
    self.md5sum.update(buf)
    self.sha1sum.update(buf)
  def digest(self):
    return self.md5sum.digest(), self.sha1sum.digest()
  def hexdigest(self):
    return self.md5sum.hexdigest(), self.sha1sum.hexdigest()


class Record:
  """One record: name, description, size, date, and checksums."""
  def __init__(self, name, dscr):
    """Initialize with name, description, and AndThenSum checksum object."""
    self.name = name
    self.dscr = dscr
    self.size = 0
    self.summer = AndThenSum()
  def update(self, buf):
    self.summer.update(buf)
    self.size += len(buf)
  def result(self):
    md5digest, sha1digest = record.summer.hexdigest()
    return self.name, self.dscr, self.size, md5digest, sha1digest


def gather_record():
  data = form["data"]
  if data.file:
    record = Record(form.getvalue('name'), form.getvalue('dscr'))
    while 1:
      buf = data.file.read(1024)
      if not buf:
        break
      else:
        record.update(buf)
    return record
  else:
    sys.stderr.write("unable to receive form data\n")
    sys.exit(1)


def escape_html(s):
  return string.replace(string.replace(string.replace(s, '&', '&amp;'),
                                       '<', '&lt;'),
                        '>', '&gt;')

def get_or_put_record(record):
  name, dscr, size, md5digest, sha1digest = record.result()

  verifying = 0

  if record.size <= 30:
    print "<p>Only records longer than 30 bytes are accepted.</p>"
    sys.exit(0)

  conn = MySQLdb.connect(user='firstrecord',
                         passwd='firstrecord',
                         db='firstrecord')
  cursor = conn.cursor()

  if not name or not dscr:
    print "<p>Individual record verification is not yet implemented,"
    print "but we can at least show you every record in the database:</p>"
    query = "SELECT name, dscr, date, size, md5, sha1 FROM firstrecord;"
    verifying = 1
  else:
    query = "INSERT INTO firstrecord "              \
            "(name, dscr, date, size, md5, sha1) "        \
            "VALUES ('%s', '%s', NOW(), %d, '%s', '%s');"  \
            % (name, dscr, size, md5digest, sha1digest)

  import _mysql_exceptions
  try:
    cursor.execute(query)
  except _mysql_exceptions.ProgrammingError, (errno, errstr):
    print "<p>There was an error processing your request:</p>"
    print "<br><ul><font color='red'>\n"
    print escape_html(errstr)
    print "</ul></font>\n"
    sys.exit(1)

  if verifying:
    plural = "s"
    if cursor.rowcount == 1:
      plural = ""
    print "<p><b>%d record%s total:</b></p>" % (cursor.rowcount, plural)
    row = cursor.fetchone()
    number = 1
    while row:
      print "<p>Record number %d:</b>"          \
            "<pre>\n"                           \
            "   Name:             %s\n"         \
            "   Description:      %s\n"         \
            "   Date:             %s\n"         \
            "   Size:             %d\n"         \
            "   MD5:              %s\n"         \
            "   SHA1:             %s\n"         \
            "</pre></p>\n"                      \
            % (number, row[0], row[1], str(row[2]), row[3], row[4], row[5])
      row = cursor.fetchone()
      number += 1
  else:
    print "<p><b>Registered:</b></b>"         \
          "<pre>\n"                           \
          "   Name:             %s\n"         \
          "   Description:      %s\n"         \
          "   Size:             %d\n"         \
          "   MD5:              %s\n"         \
          "   SHA1:             %s\n"         \
          "</pre></p>\n"                      \
          % (name, dscr, size, md5digest, sha1digest)
    print "<p>Back to <a href=\"index.html\">FirstRecord</a>.</p>"

  conn.close()


record = gather_record()
get_or_put_record(record)
