#
# Flat file pyne box. base64 filename of message id.
# Headers marshalled first, then message body.
#

import marshal
import os
import os.path
import time
import binascii
from base64 import encodestring
from base64 import decodestring
from string import find, replace
from glob import glob
from pyneheaders import *
from superbox import superbox

def id_2_hash(id):
	id = id[:160]
	x = encodestring(id)
	# some things are nasty in filenames.. yeah this is retarded
	x = replace(x, "\012", "")
	x = replace(x, "/", "|")
	# remove this junk some time
	return x[:255]

def hash_2_id(hash):
	try:
		return decodestring(replace(hash, "|", "/"))
	except binascii.Error:
		print "Eek. Couldn't decode base64 msgid: ", hash
		return None

class flatfilebox(superbox):
	# uid_prefix should be the uid normally, or if it is a
	# newsgroup we pass 'parent nntpbox uid/ newsgroup name' so
	# the newsgroup is inside the parent nntpbox. cute.
	def __init__(self, user, box, prefix=None):
		if prefix == None:
			prefix = box.uid
		self.prefix = prefix
		self.user = user

		# make sure our folder exists
		path = ""
		for i in os.path.split(self.prefix):
			path = os.path.join(path, i)
			if path == "":
				continue
			if not os.path.isdir(path):
				os.mkdir(path)

	def get_contents(self):
		files = glob(self.prefix+"/*")
		ids = []
		for i in files:
			#ids.append(hash_2_id(os.path.basename(i)))
			
			j = hash_2_id(os.path.basename(i))
			if not j:
				print "Erm. ",os.path.basename(i)
			ids.append (j)
		return ids

	def nuke(self):
		"""
		Delete database entirely.
		"""
		for i in glob(self.prefix+"/*"):
			os.remove(i)
		os.removedirs(self.prefix)

	def __del__(self):
		pass
		
	def load_header(self, msg_id):
		"""
		Return message header or None if not found. in form:
		(date, date_received, message-id, references,
		subject, from, opts (flags), senduid)
		"""
		try:
			f = open(self.prefix+"/"+id_2_hash(msg_id))
			return marshal.load(f)
		except (ValueError, TypeError, IOError, EOFError):
			return None

	def _load_article(self, msg_id):
		"""
		Returm body for message 'msg_id'.
		"""
		try:
			f = open(self.prefix+"/"+id_2_hash(msg_id))
			head = marshal.load(f)
			body = f.read()
			f.close()
			return (head, body)
		except IOError:
			return (None, None)

	def _save_article(self, headers, body_text, msg_id):
		"""
		Do not use directly. use save_article.
		"""
		s = marshal.dumps(headers)
		f = open(self.prefix+"/"+id_2_hash(msg_id), "w")
		f.write(s)
		f.write(body_text)

	def delete_article(self, msg_id):
		try:
			os.remove(self.prefix+"/"+id_2_hash(msg_id))
		except OSError:
			pass

	def has_article(self, msg_id):
		"""
		Is the article cached?
		"""
		# NOTE: we check for presence of headers not bodies
		if os.path.isfile(self.prefix+"/"+id_2_hash(msg_id)):
			return 1
		else:
			return 0




syntax highlighted by Code2HTML, v. 0.9.1