#
# Confirm a new account.  This contains the code for both the action
# and the macro.
#
import errno
import os
import time

from MoinMoin import user
from MoinMoin import util
from MoinMoin import wikiutil

#
# Macro entry point.
#
def execute(macro, args):
  message, html = confirmAccount(macro.request, macro.form)
  return html

#
# Action entry point.
#
def action(pagename, request):
  return confirmAccount(request, request.form)

#
# Return the type of user we have.
#
def user_type(u):
  if not u.id:
    return USER_INVALID
  if not hasattr(u, 'confirm_cookie'):
    return USER_VALID
  age = time.time() - float(getattr(u, 'confirm_ctime', 0))
  if age < 24 * 60 * 60 * 7:
    return USER_UNCONFIRMED
  return USER_PURGE
USER_INVALID, USER_VALID, USER_UNCONFIRMED, USER_PURGE = range(4)

#
# Remove all expired unconfirmed users.
#
def purge_users(all_users):
  now = time.time()
  purge_done = 0
  for u in all_users:
    if user_type(u) != USER_PURGE:
      continue
    purge_done = 1
    try:
      os.remove(u._User__filename())
    except EnvironmentError, e:
      if e.errno != errno.ENOENT:
        raise
    try:
      os.remove(u._User__filename() + ".trail")
    except EnvironmentError, e:
      if e.errno != errno.ENOENT:
        raise
  #
  # Purge the cache if we changed something.
  #
  if not purge_done:
    return
  try:
    os.remove(os.path.join(u._cfg.data_dir, "cache/user/name2id"))
  except EnvironmentError, e:
    if e.errno != errno.ENOENT:
      raise

#
# Pages we display.
#
pages = {
  'FormConfirmOrCancel': """
      <form method="POST" action="%(url)s"><font face="sans-serif">
	<p><font color="blue">
	  <b>Thanks for coming back!</b>
	</font></p>
	<ul>
	  <li>Name: %(user-name)s.</li>
	  <li>Email: %(user-email)s.</li>
	</ul>
	<p>
	  If these details are correct then click the
	  <b><code>Confirm</code></b> button below.
	  Otherwise click the <b><code>Cancel</code></b> button.
	</p>
	<p>
	  <input type="hidden" name="action" value="%(action)s">
	  <input type="hidden" name="i" value="%(i)s">
	  <input type="hidden" name="c" value="%(c)s">
	  <input type="submit" name="submit" value="Confirm">
	  <input type="submit" name="submit" value="Cancel">
	</p>
      </font></form>
    """,

  'FormCancel': """
      <form method="POST" action="%(url)s"><font face="sans-serif">
	<font color="red"><p align="center">
	  <b>You did not supply an authentication cookie!</b>
	</p></font>
	<p>
	  This means you can't confirm the new account.
	  But you can cancel the attempt to create your account
	  by clicking the button below.
	</p>
	<p>
	  <input type="hidden" name="action" value="%(action)s">
	  <input type="hidden" name="i" value="%(i)s">
	  <input type="submit" name="submit" value="Cancel create account">
	</p>
      </font></form>
    """,

  'ErrorNoUser': """
      <font face="sans-serif">
	<font color="red"><p align="center">
	  <b>You didn't specify what account to confirm.</b>
	</p></font>
	<p>
	  This wiki page is used for confirming new wiki accounts.
	  As you are not doing that there is nothing to see here.
	</p>
      </font>
    """,

  'ErrorBadUser': """
      <font face="sans-serif">
	<font color="red"><p align="center">
	  <b>Sorry, I can't find a matching account.</b>
	</p></font>
	<p>
	  Perhaps:
	  <ul>
	    <li>it never was created,</li>
	    <li>or its been responded to,</li>
	    <li>or it has expired (they only last a week).</li>
	  </ul>
	</p>
	<p>If you responded to it earlier you can try logging in.</p>
      </font>
    """,

  'ErrorBadCookie': """
      <font face="sans-serif">
	<font color="red"><p align="center">
	  <b><font size="+4">EH!</font><br>
	  That cookie is invalid.</b>
	</p></font>
	<p>
	  Either you are trying to hack me, or the the link you followed is
	  from an earlier account creation attempt that has been cancelled.
	  The latter explaination seems unlikely.
	</p>
      </font>
    """,

  'ErrorBadSubmit': """
      <font face="sans-serif">
	<font color="red"><p align="center">
	  <b><font size="+4">EH!</font><br>
	  What the hell does '%(submit)s' mean?.</b>
	</p></font>
	<p>
	  You are trying to hack me.  Go away!
	</p>
      </font>
    """,

  'ErrorBadResult': """
      <font face="sans-serif">
	<font color="red"><p align="center">
	  <b><font size="+4">EH!</font><br>
	  What the hell does '%(r)s' mean?!?.</b>
	</p></font>
	<p>
	  You are trying to hack me.  Go away!
	</p>
      </font>
    """,

  'Redirect': """
      <font face="sans-serif">
        You are being redirected to
	<a href="%(redirect)s">%(redirect)s</a>.
      </font>
    """,

  'ResultCancelled': """
      <font face="sans-serif">
	<p>
	  The account has been cancelled at your request.
	</p>
	<p>
	  If that is not what you wanted then create it again.
	</p>
      </font>
    """,

  'ResultConfirmed': """
      <font face="sans-serif">
	<p>
	  The account has been confirmed!
	</p>
	<p>
	  You can log in now using the <b>Login</b> link above.
	</p>
      </font>
    """,
}

def confirmAccount(request, form):
  name = form.get('n', [''])[0]
  id = form.get('i', [''])[0]
  cookie = form.get('c', [''])[0]
  submit = form.get('submit',[''])[0]
  result = form.get('r', [''])[0]
  #
  # Read in all user file.
  #
  all_users = [
      user.User(request, id=userid)
      for userid in user.getUserList(request)]
  #
  # Read in the user data.
  #
  if name:
    new_user = [u for u in all_users if u.name == name]
  elif id:
    new_user = [u for u in all_users if u.id == id]
  else:
    new_user = None
  if new_user:
    new_user = new_user[0]
  else:
    new_user = user.User(request)
    new_user.id = ''
  #
  # Calculate the variables to be inserted into the resulting page.
  #
  url = request.getScriptname() + request.getPathinfo()
  pageVars = {
      'action':		__name__.split(".")[-1],
      'c':		wikiutil.escape(cookie),
      'i':		wikiutil.escape(new_user.id),
      'r':		wikiutil.escape(result),
      'url':		url,
      'user-email':	wikiutil.escape(getattr(new_user, 'email', '')),
      'user-name':	wikiutil.escape(getattr(new_user, 'name', '')),
    }
  message = None
  redirect = ''
  if result and not result in pages:
    page = 'ErrorBadResult'
  elif not name and not id:
    page = 'ErrorNoUser'
  elif result:
    page = result
  elif user_type(new_user) != USER_UNCONFIRMED:
    page = 'ErrorBadUser'
  elif submit and submit.split()[0].lower() == 'cancel':
    del new_user.confirm_ctime
    purge_users(all_users)
    redirect = "%(url)s?r=ResultCancelled&i=%(i)s" % pageVars
    message = (
      "The account creation request for " + new_user.name +
      " has been cancelled.")
    page = 'Redirect'
  elif not cookie:
    if submit:
      page = 'ErrorSubmit'
    else:
      page = 'FormCancel'
  elif cookie != getattr(new_user, 'confirm_cookie', None):
    page = 'ErrorBadCookie'
  elif submit.lower() == 'confirm':
    new_user.disabled = 0
    del new_user.confirm_cookie
    del new_user.confirm_ctime
    new_user.save()
    purge_users(all_users)
    redirect = "%(url)s?r=ResultConfirmed&i=%(i)s" % pageVars
    message = new_user.name + "'s account has been enabled.  You can login now."
    page = 'Redirect'
  elif submit:
    page = 'ErrorBadSubmit'
  else:
    page = 'FormConfirmOrCancel'
  pageVars['redirect'] = redirect
  return message, pages[page] % pageVars


#
# Debugging only
#
def dump(structure,title=None,maxdepth=None):
  import os
  import sys
  sbin = '/usr/local/lubemobile/sbin'
  if not sbin in sys.path:
    sys.path.append(sbin)
  import rasutils
  handle = file("/tmp/moin.log", "a")
  os.chmod("/tmp/moin.log", 0666)
  d = rasutils.deeprepr(structure,maxdepth=maxdepth)
  if title != None:
    d = title + ": " + d
  handle.write(d + "\n")
  handle.close()
