Index: README.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rsvp/README.txt,v
retrieving revision 1.2
diff -u -r1.2 README.txt
--- README.txt	25 Mar 2005 06:51:25 -0000	1.2
+++ README.txt	16 Nov 2008 04:56:58 -0000
@@ -1,14 +1,87 @@
-This module lets users invite people to the events and maintain a list of
+This module lets users invite people to a node and maintains a list of
 people who will be attending.
 
-Requires the event module.
+Requires either the event or the date module to be installed.
 
 Installation
 ------------
 
-1. Copy the rsvp directory into your Drupal modules directory.
+1) Copy the rsvp directory into your Drupal modules directory.
+
+2) Go to Administer >> Site Building >> Modules and 
+
+   2.1 enable the RSVP module.
+
+   2.2 enable either the 'RSVP date connector' or the 'RSVP event connector' module. Do not enable both at the same time.
+   If you decide to switch from one connector to the other you have to use the uninstall option to uninstall the current connector before  
+   you enable the other one.
+   Be careful. Uninstalling a connector will remove all existing invitation and RSVP records. Disabling and Enabling is fine though and will not remove
+   existing RSVPs.
+
+
+Configuration
+-------------
+1) Enable permissions appropriate to your site.
+     The rsvp module provides the following permissions:
+	   "administer rsvp"      - full access
+       "maintain rsvp"        - access to all rsvp's, but no permissions to modify the general rsvp settings.
+	   "rsvp on events"       - create rsvp on nodes.
+	   "rsvp on own events"   - create rsvp on own nodes.
+	   "rsvp newsletters subscribers"  - permission to add attendees based on existing newsletters (module simplenews si required).
+	   "rsvp system users"  - permission to add users based on available roles.
+
+2) The basic difference between the event and the date module is that the date module supports reocurring events, and the creation of a Datetime field 
+is mandatory.
+
+2.1)If you use the event Module:
+From the RSVP perspective there is no other configuration required. You are set to create RSVPs for existing events.
+
+
+2.2)If you use the date Module:
+2.2.1) First you have to add a custom field of type "Datetime" or "Date" to all the content types that you want to utilize as potential events in the future. 
+   The RSVP module can manage different "event enabled" content types, but each type needs at least one datetime field.
+2.2.2) If the content types are prepared, add the content type / field associations for each content type that you want to use for RSVP's. You can do that under 
+   Adminstrator >> Site configuration >> RSVP settings >> Assocications >> Add association. The "administer rsvp" rights are required for this step. 
+   Select the content type you added a Datetime field for and press the "add" link. On the next page select the field that you want to utilize. 
+   If the field selection box is empty, you did not setup a proper field inside the content type.
+
+3) Disable Wysiwig editor for the "People you like to invite" / "Add Attendees" textarea which
+   is part of the Manage attendees form when creating a RSVP.
+
+Manage RSVP's (Admins and Moderators)
+-------------------------------------
+All RSVP's of all users can be found at 
+   Adminstrator >> Content management >> RSVP management
+   
+Create RSVP's
+--------------
+Go to the node you want to create an RSVP for and click on the RSVP tab.
+  If the RSVP tab is not available, 
+    - verify that this content type is enabled in the rsvp settings.
+    - verify that the user has the right permissions ("rsvp on events" or "rsvp on own events")
+
+
+   
+TODO:
+- Invitation reply already supports a comment field, but it needs to be displayed on the Reply overview page.
+- I would like to see a "reply/response" panel like in evite. Any Volunteers ?? Who can help here.
+- Add features like exist in Evite:
+   
+   HOST TOOL BOX
+    * › Edit Guest(s) Replies
+    * › Send a Message to Guest(s)
+    * › Remove Guest(s)
+    * › Email Me when Guest(s) Reply
+      OTHER OPTIONS
+    * › Send a free Evite eCard
+    * › Print Invitation
+    * › Mobile Alerts Phone
+    * › Change Organizer
+    * › Export Guest List
+    * › Cancel Event
+    * › Copy this Event
+    * › Add to my Outlook Calendar
+
+
 
-2. Run the rsvp.mysql file to create the needed tables (this is similar to the
-   installation of database.mysql with Drupal).
 
-3. Go to administer >> configuration >> modules and enable the rsvp module.
Index: rsvp.mysql
===================================================================
RCS file: rsvp.mysql
diff -N rsvp.mysql
--- rsvp.mysql	25 Mar 2005 06:51:25 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,24 +0,0 @@
-CREATE TABLE rsvp (
-  rid int(10) unsigned NOT NULL auto_increment,
-  nid int(10) unsigned NOT NULL default '0',
-  uid int(10) unsigned NOT NULL default '0',
-  name varchar(128) default '',
-  invite_text text,
-  blind int(3) unsigned NOT NULL default '0',
-  list_email int(3) unsigned NOT NULL default '0',
-  allow_invite int(3) unsigned NOT NULL default '0',
-  timestamp int(10) unsigned NOT NULL default '0',
-  PRIMARY KEY (rid,uid,nid)
-); 
-
-CREATE TABLE rsvp_invite (
-  response enum('yes','no','maybe','none') NOT NULL default 'none',
-  rid int(10) unsigned NOT NULL default '0',
-  uid int(10) NOT NULL default '0',
-  email varchar(128) NOT NULL default '',
-  hash varchar(255) NOT NULL default '',
-  invited int(10) unsigned NOT NULL default '0',
-  received int(10) unsigned NOT NULL default '0',
-  timestamp int(10) unsigned NOT NULL default '0',
-  PRIMARY KEY (rid,email,uid)
-);
Index: rsvp.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rsvp/rsvp.module,v
retrieving revision 1.16
diff -u -r1.16 rsvp.module
--- rsvp.module	9 Mar 2008 21:05:09 -0000	1.16
+++ rsvp.module	16 Nov 2008 04:57:01 -0000
@@ -4,40 +4,153 @@
 /**
  * @module rsvp
  * @package rsvp - A drupal module developed for civicspace - a distribution of drupal.
- * @description Provides email invite and tracking functionality for event-enabled nodes. Requires event.module.
+ * @description Provides email invite and tracking functionality for nodes. Requires event.module or date.module.
  * @author crunchywelch (welch@advomatic.com)
  * @author Omar Abdel-Wahab (owahab@gmail.com)
+ * @author Ulf Schenk (ulf@schenkunlimited.net)
  *
  */
 
-include(drupal_get_path('module', 'rsvp') .'/rsvp.theme');
+/**
+ * RSVP EMAIL ADDRESS USAGE
+ */
+define('RSVP_EMAIL_SITEADDRESS', 0);
+define('RSVP_EMAIL_SETTINGS', 1);
+define('RSVP_EMAIL_CREATOR', 2);
+
+/**
+ * RSVP ATTENDING OPTIONS
+ */
+define('RSVP_ATT_ALL',   'all');
+define('RSVP_ATT_YES',   'yes');
+define('RSVP_ATT_NO',    'no');
+define('RSVP_ATT_MAYBE', 'maybe');
+define('RSVP_ATT_NONE',  'none');
+
+/**
+ * RSVP RESPONSE OPTIONS
+ */
+define('RSVP_RESPONSE_SHOW',   0);
+define('RSVP_RESPONSE_HIDE',   1);
+define('RSVP_RESPONSE_SHOWWHENREPLIED',   2);
+
+/**
+ * RSVP ATTENDEE OPTIONS
+ */
+define('RSVP_ATTENDEE_SHOW',   0);
+define('RSVP_ATTENDEE_HIDE',   1);
+
 
 /**
  * @defgroup rsvp_core core functions for rsvp.
  */
 
 /**
+ * Implementations of hook_views_api().
+ */
+function rsvp_views_api() {
+  return array(
+    'api' => 2,
+    'path' => drupal_get_path('module','rsvp'),
+  );
+}
+
+/**
+ * Implementation of hook_theme.
+ */
+function rsvp_theme() {
+  return array(
+    'rsvp_send_status' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('status' => NULL),
+    ),
+    'rsvp_event' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('node' => NULL),
+      'arguments' => array('startdate' => NULL),
+    ),
+    'rsvp_event_anonymous' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array(),
+    ),
+    'rsvp_invite' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('invite' => NULL),
+      'arguments' => array('rsvp' => NULL),
+      'arguments' => array('content' => NULL),
+    ),
+    'rsvp_preview' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('content' => NULL),
+    ),
+    'rsvp' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('rsvp' => NULL),
+      'arguments' => array('content' => NULL),
+    ),
+    'rsvp_reply' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('content' => NULL),
+    ),
+    'rsvp_invite_action' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('content' => NULL),
+    ),
+    'rsvp_help' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('content' => NULL),
+    ),
+    'rsvp_invite_mail_subject' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('invite' => NULL),
+      'arguments' => array('subject' => NULL),
+    ),
+    'rsvp_invite_mail' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('invite' => NULL),
+    ),
+    'rsvp_message_mail_subject' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('invite' => NULL),
+      'arguments' => array('subject' => NULL),
+    ),
+    'rsvp_message_mail' => array(
+      'file' => 'rsvp.theme',
+      'arguments' => array('invite' => NULL),
+      'arguments' => array('sender' => NULL),
+      'arguments' => array('body' => NULL),
+    ),
+    
+  );
+}
+
+/**
  * Provides a pathetically small amount of help information for the rsvp module.
  *
  * @ingroup rsvp_core
  */
 function rsvp_help($path, $arg) {
-  switch ($path) {
+    switch ($path) {
     case 'admin/help#rsvp':
-      global $user;
-      $output = '<p>'. t('The RSVP module lets users invite people by email to events and track a list of people who will be attending.    The RSVP module requires the event module because it is necessary to have an event to invite people to first.') .'</p>';
+    	
+    	global $user;
+      $output = '<p>'. t('The RSVP module lets users invite people by email to events and track a list of people who will be attending.    The RSVP module requires either the event module or the date module because it is necessary to specify a content type to invite people to first.') .'</p>';
       $output .= '<p>'. t('The RSVP module also lets users invite users subscribed to newsletters, which requires !simplenews installed, as well as invite other registered users.', array('!simplenews' => l(t('Simplenews module'), 'http://drupal.org/project/simplenews'))) .'</p>';
-      $output .= '<p>'. t('The RSVP page shows a <em>RSVP</em> tab in event page and in <em>my account</em> page. There are confirmation screens for creating and editing RSVPs. Email addresses which are input for RSVP have input validation.  RSVP also creates an invitation url by hash value access so that users can click a URL and be taken directly to their invitation. For each RSVP there are view, edit, manage, and send tabs. Users can manage attendees through the manage attendees tab. Users can also send attendees a message through the send message tab.') .'</p>';
+      $output .= '<p>'. t('The RSVP page shows a <em>RSVP</em> tab in the content type page and in <em>my account</em> page. There are confirmation screens for creating and editing RSVPs. Email addresses which are input for RSVP have input validation.  RSVP also creates an invitation url by hash value access so that users can click a URL and be taken directly to their invitation. For each RSVP there are view, edit, manage, and send tabs. Users can manage attendees through the manage attendees tab. Users can also send attendees a message through the send message tab.') .'</p>';
       $output .= t('<p>You can:</p>
 <ul>
-<li>Enable the RSVP module at <a href="!admin-modules">administer &gt;&gt; modules</a>.</li>
-<li>Not administer the RSVP module.</li>
-<li>Create an RSVP for an event by clicking the <strong>Create RSVP</strong> in the RSVP tab in your event.</li>
+<li>Enable the RSVP module at !admin-modules.</li>
+<li>Create an RSVP for an event by clicking the <strong>Create RSVP</strong> link in the RSVP tab in your content type.</li>
 <li>View your invites at !rsvp.</li>
 <li>View your RSVPs at !rsvp-manage.</li>
 <li>View, edit, and invite more attendees for each RSVP.</li>
-', array('!admin-modules' => url('admin/build/modules'), '!rsvp' => l(t('your invites tab'), 'user/'. $user->uid .'/rsvp'), '!rsvp-manage' => l(t('your RSVPs tab'), 'user/'. $user->uid .'/rsvp/manage'))) .'</ul>';
-      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%rsvp">RSVP page</a>.', array('%rsvp' => 'http://www.drupal.org/handbook/modules/rsvp/')) .'</p>';
+<li>Manage all RSVPs at !rsvp-content.</li>
+', array('!admin-modules' => l(t('administer &gt;&gt; modules'), 'admin/build/modules'), 
+         '!rsvp' => l(t('your invites tab'), 'user/'. $user->uid .'/rsvp'), 
+         '!rsvp-manage' => l(t('your RSVPs tab'), 'user/'. $user->uid .'/rsvp/manage'), 
+         '!rsvp-content' => l(t('Administer &gt;&gt; Content management &gt;&gt; RSVP management'),'admin/content/rsvp')) ) .'</ul>';
+      
+      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="!rsvp">RSVP page</a>.', array('!rsvp' => url('http://www.drupal.org/handbook/modules/rsvp/', array('external' => TRUE)))) .'</p>';
       return $output;
     case 'admin/modules#description' :
       return t('Provides rsvp functionality for node types enabled in the event system.');
@@ -60,7 +173,7 @@
  * @ingroup rsvp_core
  */
 function rsvp_perm() {
-  return array("administer rsvp", "rsvp on events", "rsvp on own events", "rsvp newsletters subscribers", "rsvp system users");
+  return array("administer rsvp", "maintain rsvp", "rsvp on events", "rsvp on own events", "rsvp newsletters subscribers", "rsvp system users");
 }
 
 /**
@@ -76,133 +189,325 @@
  * Implementation of hook_menu().
  */
 function rsvp_menu() {
+
   global $user;
+  $connector = new RsvpConnector();
+  
   $items = array();
 
+  //admin settings tab
+  $items['admin/settings/rsvp'] = array(
+    'title' => 'RSVP settings',
+    'type' => MENU_NORMAL_ITEM,
+    'description' => 'Set up RSVP related options.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_admin_settings_general'),
+    'access arguments' => array('administer rsvp'),
+    'description' => 'Configure general RSVPs settings.',
+  );
+  
+  $items['admin/settings/rsvp/general'] = array(
+    'title' => 'General',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_admin_settings_general'),
+    'access arguments' => array('administer rsvp'),
+    'weight' => -10,
+    'description' => 'Manage RSVPs.',
+  );
+
+  $items['admin/settings/rsvp/types'] = array(
+    'title' => 'Associations',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_admin_settings_types'),
+    'access callback' => 'rsvp_admin_type_access',
+    'access arguments' => array($connector),
+    'weight' => -9,
+    'description' => 'Manage associations with content types that you want to use with rsvp.',
+  );
+
+  $items['admin/settings/rsvp/types/list'] = array(
+    'title' => 'List associations',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_admin_settings_types'),
+    'access callback' => 'rsvp_admin_type_access',
+    'access arguments' => array($connector),
+    'weight' => -8,
+    'description' => 'Manage associations with content types that you want to use with rsvp.',
+  );
+  
+  $items['admin/settings/rsvp/types/add'] = array(
+    'title' => 'Add association',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_admin_settings_types_add'),
+    'access callback' => 'rsvp_admin_type_access',
+    'access arguments' => array($connector),
+    'weight' => -7,
+    'description' => 'Add a association with a content type that you want to use with rsvp.',  
+  );
+  
+  $items['admin/settings/rsvp/types/add/%'] = array(
+    'title' => 'Select field for association',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_admin_settings_types_add_field', 5),
+    'access callback' => 'rsvp_admin_type_access',
+    'access arguments' => array($connector),
+  );
+    
+  $items['admin/settings/rsvp/types/delete/%'] = array(
+    'title' => 'Delete association',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_admin_settings_types_delete', 5),
+    'access callback' => 'rsvp_admin_type_access',
+    'access arguments' => array($connector),
+  );
+  
+  //admin content tab
+  $items['admin/content/rsvp'] = array(
+    'title' => 'RSVP management',
+    'type' => MENU_NORMAL_ITEM,
+    'description' => 'Manage all RSVPs.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_manage', NULL, NULL, true),
+    'access arguments' => array('maintain rsvp'),
+    'description' => 'Manage RSVPs.',
+  );
+  
+  
   // user account tabs
-  if ($user->uid != 0) {
-    $items['user/%user/rsvp'] = array(
-                      'title' => t('RSVP'),
-                      'page callback' => 'rsvp_view_invites',
-                      'page arguments' => array($user->uid),
-                      'type' => MENU_LOCAL_TASK,
-                      'access arguments' => array('access content'),
-                    );
-    $items['user/%user/rsvp/invites'] = array(
-                      'title' => t('Your invites'),
-                      'access arguments' => array('access content'),
-                      'type' => MENU_DEFAULT_LOCAL_TASK,
-                      'weight' => '0');
-
-    $items['user/%user/rsvp/manage'] = array(
-                      'title' => t('Your RSVPs'),
-                      'access arguments' => array('access content'),
-                      'page callback' => 'rsvp_manage',
-                      'type' => MENU_LOCAL_TASK,
-                      'weight' => '1');
-    drupal_set_html_head(_rsvp_html_head());
-    // email response path
-    $items['rsvp/email'] = array(
-                     'title' => t('View invite'),
-                     'page callback' => 'rsvp_view_invite',
-                     'page arguments' => array(arg(2), arg(3)),
-                     'access arguments' => array('access content'),
-                     'type' => MENU_CALLBACK);
-  }
-
-  if (arg(0) == 'node' && is_numeric(arg(1))) {
-    $nid = arg(1);
-    $node = node_load($nid);
-    $rid = arg(3);
-    $access = (user_access('administer rsvp') || user_access('rsvp on events') || ($node->uid == $user->uid && user_access('rsvp on own events')));
-    if (event_is_enabled($node->type)) {
-      // define access rights
-      // viewing tabs
-      $items['node/'. $nid .'/rsvp'] = array(
-                        'title' => t('RSVP'),
-                        'access' => $access,
-                        'type' => MENU_LOCAL_TASK,
-                        'callback' => 'rsvp_manage',
-                        'callback arguments' => array($nid),
-                        'weight' => 3,
-                      );
-      $items['node/'. $nid .'/rsvp/create'] = array(
-                        'title' => t('Create RSVP'),
-                        'access' => $access,
-                        'callback' => 'drupal_get_form',
-                        'callback arguments' => array('rsvp_addedit_form', $nid),
-                        'type' => MENU_CALLBACK);
-      // management tabs
-      if (is_numeric($rid)) {
-        // rsvp paths
-        $items['node/'. $nid .'/rsvp/'. $rid .'/view'] = array(
-                          'title' => t('View'),
-                          'access' => $access,
-                          'callback' => 'rsvp_view',
-                          'callback arguments' => array($rid),
-                          'type' => MENU_LOCAL_TASK,
-                          'weight' => '0');
-        $items['node/'. $nid .'/rsvp/'. $rid .'/edit'] = array(
-                          'title' => t('Edit'),
-                          'access' => $access,
-                          'callback' => 'drupal_get_form',
-                          'callback arguments' => array('rsvp_addedit_form', $nid, $rid),
-                          'type' => MENU_LOCAL_TASK,
-                          'weight' => '1');
-        $items['node/'. $nid .'/rsvp/'. $rid .'/attendees'] = array(
-                          'title' => t('Manage attendees'),
-                          'access' => $access,
-                          'callback' => 'rsvp_attendees',
-                          'callback arguments' => array($rid),
-                          'type' => MENU_LOCAL_TASK,
-                          'weight' => '2');
-        $items['node/'. $nid .'/rsvp/'. $rid .'/attendees/send'] = array(
-                          'title' => t('Send invites'),
-                          'access' => $access,
-                          'callback' => 'rsvp_attendees_send_invites',
-                          'callback arguments' => array($rid, 'node/'. $nid .'/rsvp/'. $rid .'/attendees'),
-                          'type' => MENU_CALLBACK,
-                          'weight' => '2');
-        $items['node/'. $nid .'/rsvp/'. $rid .'/attendees/csv'] = array(
-                          'title' => t('manage attendees'),
-                          'access' => $access,
-                          'callback' => 'rsvp_attendees_csv',
-                          'callback arguments' => array($rid),
-                          'type' => MENU_CALLBACK,
-                          'weight' => '2');
-        $items['node/'. $nid .'/rsvp/'. $rid .'/attendees/simplenews'] = array(
-                          'access' => ($access && user_access('rsvp newsletters subscribers')),
-                          'callback' => 'rsvp_attendees_simplenews',
-                          'callback arguments' => array(arg(6)),
-                          'type' => MENU_CALLBACK,
-                          'weight' => '2');
-        $items['node/'. $nid .'/rsvp/'. $rid .'/attendees/role'] = array(
-                          'access' => ($access && user_access('rsvp system users')),
-                          'callback' => 'rsvp_attendees_users',
-                          'callback arguments' => array(arg(6)),
-                          'type' => MENU_CALLBACK,
-                          'weight' => '2');
-        $items['node/'. $nid .'/rsvp/'. $rid .'/message'] = array(
-                          'title' => t('Send message'),
-                          'access' => $access,
-                          'callback' => 'drupal_get_form',
-                          'callback arguments' => array('rsvp_message_form', $rid),
-                          'type' => MENU_LOCAL_TASK,
-                          'weight' => '3');
-        $items['node/'. $nid .'/rsvp/'. $rid .'/delete'] = array(
-                          'title' => t('Delete RSVP'),
-                          'access' => $access,
-                          'callback' => 'drupal_get_form',
-                          'callback arguments' => array('rsvp_delete_form', $rid),
-                          'type' => MENU_CALLBACK);
-      }
-    }
-  }
+  $items['user/%user/rsvp'] = array(
+    'title' => 'RSVP',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_view_invites', 1),
+    'access arguments' => array('access content'),
+  );
+    
+  $items['user/%user/rsvp/invites'] = array(
+    'title' => 'Your invites',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_view_invites', 1),
+    'access arguments' => array('access content'),
+    'weight' => '0',
+  );
+
+  $items['user/%user/rsvp/manage'] = array(
+    'title' => 'Your RSVPs',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_manage', NULL, 1, false),
+    'access arguments' => array('access content'),
+    'weight' => '1',
+  );
+      
+  drupal_set_html_head(_rsvp_html_head());
+    
+  // email response path
+  $items['rsvp/email/%rsvp_hash/remove'] = array(
+    'title' => 'Remove attendee from invite',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_invite_remove_attendee_form', 2),
+    'access arguments' => array('access content'),
+  );
+  $items['rsvp/email/%rsvp_hash/status'] = array(
+    'title' => 'Status of attendee',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_invite_status_attendee_form', 2),
+    'access arguments' => array('access content'),
+  );
+  $items['rsvp/email/%rsvp_hash'] = array(
+    'title' => 'View invitation',
+    'type' => MENU_NORMAL_ITEM,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_invite_view_form', 2),
+    'access arguments' => array('access content'),
+  );
+  $items['rsvp/email/%rsvp_hash/view'] = array(
+    'title' => 'View invitation',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_invite_view_form', 2),
+    'access arguments' => array('access content'),
+    'weight' => 0,
+  );
+  $items['rsvp/email/%rsvp_hash/attendees'] = array(
+    'title' => 'Attendees',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_attendee_hash_form', 2),
+    'access callback' => 'rsvp_user_attendees_view_access',
+    'access arguments' => array($connector, 2),
+    'weight' => 1,
+  );
+  $items['rsvp/email/%rsvp_hash/message'] = array(
+    'title' => 'Send message',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_message_hash_form', 2),
+    'access callback' => 'rsvp_message_hash_access',
+    'access arguments' => array($connector, 2),
+    'weight' => 2,
+  );
+  
+  
+//    $rid = arg(3);
+  $items['node/%node/rsvp'] = array(
+    'title' => 'RSVP',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_manage', 1, NULL, false),
+    'access callback' => 'rsvp_user_node_access',
+    'access arguments' => array($connector, 1),
+    'weight' => 3,
+  );
+  $items['node/%node/rsvp/create'] = array(
+    'title' => 'Create RSVP',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_addedit_form', 1),
+    'access callback' => 'rsvp_user_node_access',
+    'access arguments' => array($connector, 1),
+  );
+
+  // rsvp management tabs
+  $items['rsvp/%rsvp'] = array(
+    'title' => 'View',
+    'type' => MENU_NORMAL_ITEM,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_view_form', 1),
+    'access callback' => 'rsvp_user_rsvp_access',
+    'access arguments' => array($connector, 1),
+    'weight' => '0',
+  );
+  $items['rsvp/%rsvp/view'] = array(
+    'title' => 'View',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_view_form', 1),
+    'access callback' => 'rsvp_user_rsvp_access',
+    'access arguments' => array($connector, 1),
+    'weight' => '0',
+  );
+  $items['rsvp/%rsvp/edit'] = array(
+    'title' => 'Edit',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_addedit_form', NULL, 1),
+    'access callback' => 'rsvp_user_rsvp_access',
+    'access arguments' => array($connector, 1),
+    'weight' => '1',
+  );
+  $items['rsvp/%rsvp/attendees'] = array(
+    'title' => 'Manage attendees',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_attendee_form', 1),
+    'access callback' => 'rsvp_user_rsvp_access',
+    'access arguments' => array($connector, 1),
+    'weight' => '2',
+  );
+  $items['rsvp/%rsvp/attendees/send'] = array(
+    'title' => 'Send invites',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_attendees_send_invites_form', 1),
+    'access callback' => 'rsvp_user_rsvp_access',
+    'access arguments' => array($connector, 1),
+    'weight' => '2',
+  );
+  $items['rsvp/%rsvp/attendees/csv'] = array(
+    'title' => 'manage attendees',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_attendees_csv_form', 1),
+    'access callback' => 'rsvp_user_attendees_cvs_access',
+    'access arguments' => array(1),
+    'weight' => '2',
+  );
+  $items['rsvp/%rsvp/attendees/simplenews/%'] = array(
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_attendees_simplenews_form', 1, 4),
+    'access callback' => 'rsvp_user_rsvp_access',
+    'access arguments' => array($connector, 1, 'rsvp newsletters subscribers'),
+    'weight' => '2',
+  );
+  $items['rsvp/%rsvp/attendees/role/%'] = array(
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_attendees_users_form', 1, 4),
+    'access callback' => 'rsvp_user_rsvp_access',
+    'access arguments' => array($connector, 1, 'rsvp system users'),
+    'weight' => '2',
+  );
+  $items['rsvp/%rsvp/message'] = array(
+    'title' => 'Send message',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_message_form', 1),
+    'access callback' => 'rsvp_user_rsvp_access',
+    'access arguments' => array($connector, 1),
+    'weight' => '3',
+  );
+  $items['rsvp/%rsvp/delete'] = array(
+    'title' => 'Delete RSVP',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rsvp_delete_form', 1),
+    'access callback' => 'rsvp_user_rsvp_access',
+    'access arguments' => array($connector, 1),
+  );
 
   return $items;
 }
 
 /**
+ * Provides the links that should be displayed when viewing rsvp.
+ *
+ * @param $type the type of link (for example, 'node', 'page', or 'system') being requested
+ * @param $node the node that is requesting the link.  This is used in conjunction with $type to further determine
+ *        what sort of link to display.
+ * @return an array of links, or an empty array if no links apply for the criteria passed to this method.
+ */
+function rsvp_link($type, $node = NULL, $teaser = FALSE) {
+  $links = array();
+  
+  if ($type == 'node') {
+  	
+    $connector = new RsvpConnector();
+  	
+    global $user;
+  	// node links
+    $field = _rsvp_getField($node->type);
+    $invites = _rsvp_get_node_invites($node->nid, $user->uid);
+    while ($invite = db_fetch_object($invites)) {
+        $pos = $connector->get_posByHash($node, $field, $invite->startdate /*derived by query*/);
+        if ($pos >= 0) {
+          $startdate = $connector->get_startdateAsString($node, $field, $pos);
+        }
+        else {
+          $startdate = 'UNKNOWN STARTDATE:' . $invite->startdate; 
+        }
+    	
+    	$links['rsvp_invite'] = array('title' => t('View invitation(' . $startdate . ')'), 
+                                      'href' => 'rsvp/email/'. $invite->hash . '/view',
+                                     );
+    }
+  }
+  
+  return $links;
+}
+
+
+/**
 * Act on nodes defined by other modules.
 *
 * @ingroup rsvp_functions
@@ -211,8 +516,11 @@
 * @return dbresultset of the requested rsvp.
 */
 function rsvp_nodeapi(&$node, $op) {
-  // delete all RSVPs associated with an event when the event is deleted
-  if ($op == 'delete' && event_is_enabled($node->type)) {
+  
+  $connector = new RsvpConnector();
+	
+  // delete all RSVPs associated with a node when the node is deleted
+  if ($op == 'delete' && $connector->is_event_enabled($node->type)) {
     $list = _rsvp_get_node_invites($node->nid);
     while ($rsvp = db_fetch_object($list)) {
       rsvp_delete($rsvp->rid);
@@ -221,6 +529,37 @@
 }
 
 /**
+* Retrieves an rsvp from the database and is doing some basic checks
+  If node is null, exclude node specific tests.
+*
+* @ingroup rsvp_functions
+* @param $rid The rid of the rsvp instance.
+* @param $node The node object related to the expected rsvp instance.
+* @return dbresultset of the requested rsvp or false;
+*/
+function rsvp_load_and_test($rid, $node = NULL) {
+
+  if (is_null($rid) || !is_numeric($rid)) {
+    drupal_set_message(t('Rsvp %rid does not exist.', array('%rid' => $rid)), 'error');
+    return false;
+  }
+
+  $rsvp = rsvp_load($rid);
+
+  if ($rsvp == false) { 
+    drupal_set_message(t('Rsvp %rid does not exist.', array('%rid' => $rid)), 'error');
+    return false;
+  }
+  
+  if (!is_null($node) && $node->nid != $rsvp->nid) { 
+    drupal_set_message(t('Rsvp %rid does not belong to Node %node.', array('%rid' => $rid, '%node' => $nid)), 'error');
+    return false;
+  }
+  
+  return $rsvp;
+}
+  
+/**
 * Retrieves an rsvp from the database.
 *
 * @ingroup rsvp_functions
@@ -232,67 +571,175 @@
 }
 
 /**
+* Retrieves an invitation from the database based on a hash.
+*
+* @ingroup rsvp_functions
+* @param $hash The hash of a invite instance.
+* @return dbresultset of the requested rsvp.
+*/
+function rsvp_hash_load($hash) {
+  
+  $invite = _rsvp_get_invite_by_hash($hash);
+
+  // check if the invitation exists
+  if (!$invite->rid) {
+  	return false;
+  }
+  
+  return $invite;
+}
+
+/**
 * Handles the rsvp manage requests.
 *
-* @ingroup rsvp_core
+* @ingroup rsvp
+* @param $node The node object you want to manage the rsvp instances for, or all nodes.
+* @param $usr The user. If NULL show rsvps for the loged in user.
+* @param $allUsers Boolean If true show rsvps for all users.
 * @return themed rsvp manage response.
+*
+* This form is being called from three places:
+* - Through User account (user/%uid/rsvp/manage):
+*       params: NULL, $user, false
+* 
+* - Through Nodes: The User selects a node and then clicks the RSVP tab if visible(node/%node/rsvp):
+*       params: $node, NULL, false
+* 
+* - The RSVP management page (admin/content/rsvp)
+*       params: NULL, NULL, true 
+*      
+* 
+* 
 */
-function rsvp_manage($nid = NULL) {
+function rsvp_manage(&$form_state, $node = NULL, $usr = NULL, $allUsers = false) {
+  
+  if (is_null($usr)) {
+    global $user;
+    $usr = $user;
+  }
 
-  $header = array(
-    array('data' => t('Title'), 'field' => 'name', 'sort' => 'asc', 'width' => '30%'), 
-    t('Invites'),
-    t('Attending'),
-    t('Not attending'),
-    t('Might attend'),
-    t('No response'),
-    array('data' => t('Operations'), 'colspan' => 3),
-  );
+  $form = array();
+  
+  $allNodes = (is_null($node));
+  
+  $connector = new RsvpConnector();
+  
+  //set breadcrumb trail only if we do not come through Administration/Content Management
+  if ($allNodes == false || $allUsers == false) {
+    // Set the breadcrumb trail.
+    drupal_set_breadcrumb(array(l(t('Home'), NULL), l('My account', 'user/'. $usr->uid)));
+    drupal_set_title(check_plain($usr->name));
+    $form['title'][] = array('#value' => '<br /><div><h3>' . t('Your created RSVPs'). '</h3></div>');
+  }
+  else {
+    $form['title'][] = array('#value' => '<br /><div><h3>' . t('All RSVPs') . '</h3></div>');
+  }
+  
+  $header = array();
+  
+  if ($allNodes == true) {
+    $header[] = array('data' => t('Node'), 'field' => 'title');
+  }
+  $header[] = array('data' => t('Title'), 'field' => 'name', 'sort' => 'asc', 'width' => '20%');
+  if ($allUsers == true) {
+    $header[] = t('User');
+  }
+  
+  $header[] = t('Startdate');
+  $header[] = t('Inv.');
+  $header[] = t('Yes');
+  $header[] = t('No');
+  $header[] = t('Maybe');
+  $header[] = t('No resp.');
+  $header[] = array('data' => t('Operations'), 'colspan' => 3);
 
-  if ($nid) {
-    global $user;
-    $node = node_load($nid);
-    drupal_set_title($node->title);
-    if (user_access('administer rsvp') || user_access('rsvp on events') || (user_access('rsvp on own events') && $node->uid == $user->uid)) {
-      if ($node->event_end > time()) {
-        $content = l(t('Create RSVP'), 'node/'. $nid .'/rsvp/create');
+
+  
+  if (!$allNodes) {
+    $end_dates = array();
+    $field = _rsvp_getField($node->type);
+    drupal_set_title(check_plain($node->title));
+    if (rsvp_user_node_access($connector, $node)) {
+        $allExpired = true;
+        $count = $connector->get_datecount($node, $field);
+        //iterate through all specified enddates (in case of repeating dates)
+        $time = time();
+        $end_dates[] = array('current time stamp' => $time, 'current time readable' => date('r', $time) );
+        for ($i = 0; $i < $count; $i++) {
+          $t2 = $connector->get_enddate($node, $field, $i);
+          $end_dates[] = array('field' => $field, 'stamp' => $t2, 'readable' => date('r', $t2) );
+          
+          if ($t2 > $time) {
+            $allExpired = false;
+            break;
+          }
+        }
+        //var_dump($allExpired, $end_dates);
+        
+      if ($allExpired == false) {
+        $content = l(t('Create RSVP'), 'node/'. $node->nid .'/rsvp/create');
       }
       else {
         $content = t('This event has expired, invitations can only be sent to events <br />that have not expired yet.');
       }
+      $form['content'] = array(
+        '#value' => $content,
+      );      
     }
   }
-  else {
-    $header = array_merge(array(array('data' => t('Event'), 'field' => 'title')), $header);
-  }
 
   $rows = array();
-  $rsvps = _rsvp_get_rsvps($nid, NULL, tablesort_sql($header));
+  $rsvps = _rsvp_get_rsvps(is_null($node) ? NULL : $node->nid, (($allUsers == true) ? NULL : $usr->uid), tablesort_sql($header));
 
   while ($rsvp = db_fetch_object($rsvps)) {
+    $field = NULL;
+    if ($allNodes) {
+        $node = node_load($rsvp->nid);
+    }
+    if ($allUsers) {
+        $usr = user_load($rsvp->uid);
+    }
+    
+    
+    $field = _rsvp_getField($node->type);
+    
     $row = array();
-    is_null($nid) ? $row[] = l($rsvp->title, 'node/'. $rsvp->nid, array('title' => 'View event')) : '';
-    $row[] = l($rsvp->name, 'node/'. $rsvp->nid .'/rsvp/'. $rsvp->rid .'/view', array('title' => 'View RSVP'));
+    ($allNodes == true) ? $row[] = l($node->title, 'node/'. $rsvp->nid, array('attributes' => array('title' => 'View node'))) : '';
+    $row[] = l($rsvp->name, 'rsvp/'. $rsvp->rid .'/view', array('attributes' => array('title' => 'View RSVP')));
+    ($allUsers == true) ? $row[] = l($usr->name, 'user/'. $rsvp->uid, array('attributes' => array('title' => 'View User'))) : '';
+    
+    $pos = $connector->get_posByHash($node, $field, $rsvp->startdate);
+    $row[] = $connector->get_startdateAsString($node, $field, $pos);
     // add statistics
-    $row[] = db_result(_rsvp_get_attendees($rsvp->rid, 'all', TRUE));
-    $row[] = db_result(_rsvp_get_attendees($rsvp->rid, 'yes', TRUE));
-    $row[] = db_result(_rsvp_get_attendees($rsvp->rid, 'no', TRUE));
-    $row[] = db_result(_rsvp_get_attendees($rsvp->rid, 'maybe', TRUE));
-    $row[] = db_result(_rsvp_get_attendees($rsvp->rid, 'none', TRUE));
-    $row[] = l(t('Edit'), 'node/'. $rsvp->nid .'/rsvp/'. $rsvp->rid .'/edit', array('title' => 'Edit RSVP'));
-    $row[] = l(t('Invite'), 'node/'. $rsvp->nid .'/rsvp/'. $rsvp->rid .'/attendees', array('title' => 'Invite more people to attend your rsvp'));
-    $row[] = l(t('Send a message'), 'node/'. $rsvp->nid .'/rsvp/'. $rsvp->rid .'/message', array('title' => 'Send people you invited a message'));
+    $row[] = db_result(_rsvp_get_attendees($rsvp->rid, RSVP_ATT_ALL, TRUE));
+    $row[] = db_result(_rsvp_get_attendees($rsvp->rid, RSVP_ATT_YES, TRUE));
+    $row[] = db_result(_rsvp_get_attendees($rsvp->rid, RSVP_ATT_NO, TRUE));
+    $row[] = db_result(_rsvp_get_attendees($rsvp->rid, RSVP_ATT_MAYBE, TRUE));
+    $row[] = db_result(_rsvp_get_attendees($rsvp->rid, RSVP_ATT_NONE, TRUE));
+    $row[] = l(t('Edit'), 'rsvp/'. $rsvp->rid .'/edit', array('attributes' => array('title' => 'Edit RSVP')));
+    $row[] = l(t('Manage attendees'), 'rsvp/'. $rsvp->rid .'/attendees', array('attributes' => array('title' => 'Invite more people to attend your rsvp')));
+    $row[] = l(t('Send message'), 'rsvp/'. $rsvp->rid .'/message', array('attributes' => array('title' => 'Send people you invited a message')));
     $rows[] = $row;
   }
-  if (count($rows)) {
-    $content .= theme('table', $header, $rows);
+  
+  if ($pager = theme('pager', NULL, 10, 0)) {
+    $rows[] = array(array('data' => $pager, 'colspan' => count($header)));
   }
 
-  if (!$content) {
-    // no RSVPs found for the requested user
-    $content = t('You don\'t have any RSVPs.');
+  if (!$rows) {
+    if ($allUsers) {  	
+  	  $form['content2'] = array('#value' => '<p>'. t('No RSVPs. available') .'</p>');
+    }
+    else {
+      $form['content2'] = array('#value' => '<p>'. t('You don\'t have created any RSVPs for this node.') .'</p>');
+    }      
+  }
+  else {
+    $table = theme('table', $header, $rows);
+    $form['table'] = array('#value' => $table);
   }
-  return $content;
+  
+  return $form;
 }
 
 /**
@@ -301,7 +748,7 @@
 * @ingroup rsvp_functions
 * @param $attendees either an array or a string with line delimited email addresses.
 * @param $rid The id of the rsvp instance.
-* @return boolean true if successful
+* @return array with failed emailaddresses
 */
 function rsvp_set_invites($attendees, $rid) {
   $emails = array();
@@ -311,44 +758,72 @@
   $attendees = array_unique($attendees);
 
   foreach ($attendees as $key => $value) {
-    // strip whitespace
+    
+  	$list_key = NULL;
+    $invite_hash = NULL;
+  	
+  	// strip whitespace
     $string = trim($value);
-    // attempt to deal with the string as a drupal username
-    // we do this before dealing it as an e-mail to handle users like 
-    // foo@somesite.com
-    $user = user_load(array('name' => $string));
-    if ($user === FALSE) {
-      // attempt to find a system user having this string as an e-mail address
-      $user = user_load(array('mail' => $string));
+    
+    if (strlen($string)) {
+      // attempt to deal with the string as a drupal username
+      // we do this before dealing it as an e-mail to handle users like 
+      // foo@somesite.com
+      $user = user_load(array('name' => $string));
       if ($user === FALSE) {
-        // no user found: carry on dealing with the string as an e-mail address
-        if (strlen($string) && valid_email_address($string)) {
-          if (!_rsvp_attendee_exists($rid, $string)) {
-            // if this e-mail is not in the attendee list,
-            // add it
-            db_query('INSERT INTO {rsvp_invite} (rid, email, hash, timestamp) VALUES (%d, \'%s\', \'%s\', %d)', $rid, $string, md5($rid . $string . time()), time());
+        // attempt to find a system user having this string as an e-mail address
+        $user = user_load(array('mail' => $string));
+        if ($user === FALSE) {
+          // no user found: carry on dealing with the string as an e-mail address
+          if (valid_email_address($string)) {
+          	$invite = _rsvp_attendee_exists($rid, $string);
+            if (!$invite) {
+              // if this e-mail is not in the attendee list,
+              // add it
+              $hash = md5($rid . $string . time());
+              if (db_query('INSERT INTO {rsvp_invite} (rid, email, hash, timestamp, response, comment) VALUES (%d, \'%s\', \'%s\', %d, \'%s\', \'%s\')', $rid, $string, $hash, time(), 'none', '')) {
+                $invite_hash = $hash;
+                $list_key = 'success_add';
+              }
+            }
+            else {
+              // the e-mail is already in the attendee list
+              $invite_hash = $invite->hash;
+              $list_key = 'existing';
+            }
           }
           else {
-            // the e-mail is already in the attendee list
-            $emails['existing'][] = $string;
+            // the e-mail is invalid
+            $invite_hash = NULL;
+            $list_key = 'invalid';
           }
         }
+      }
+
+      if ($user != FALSE) {
+        // a valid drupal user was found, make sure his/her e-mail isn't already
+        // in the attendees list
+        $invite = _rsvp_attendee_exists($rid, $user->mail);
+      	if (!$invite) {
+          $hash = md5($rid . $string . time());
+          if (db_query('INSERT INTO {rsvp_invite} (rid, uid, email, hash, timestamp, response, comment) VALUES (%d, %d, \'%s\', \'%s\', %d, \'%s\', \'%s\')', $rid, $user->uid, $user->mail, $hash, time(), 'none', '')) {
+            $invite_hash = $hash;
+            $list_key = 'success_add';
+          }          
+        }
         else {
-          // the e-mail is invalid
-          $emails['invalid'][] = $string;
+          // the e-mail is already in the attendee list
+          $invite_hash = $invite->hash;
+          $list_key = 'existing';
         }
       }
-    }
-
-    if ($user !== FALSE) {
-      // a valid drupal user was found, make sure his/her e-mail isn't already
-      // in the attendees list
-      if (!_rsvp_attendee_exists($rid, $user->mail)) {
-        db_query('INSERT INTO {rsvp_invite} (rid, uid, email, hash, timestamp) VALUES (%d, %d, \'%s\', \'%s\', %d)', $rid, $user->uid, $user->mail, md5($rid . $string . time()), time());
+      
+      if ($invite_hash != NULL) {
+        $invite = _rsvp_get_invite_by_hash($invite_hash);
+        $emails[$list_key][] = _rsvp_getAttendeeEmail($invite);
       }
       else {
-        // the e-mail is already in the attendee list
-        $emails['existing'][] = $user->name;
+        $emails[$list_key][] = $string;
       }
     }
   }
@@ -356,332 +831,557 @@
   return $emails;
 }
 
+
 /**
 * Handles the rsvp invites requests.
 *
-* @ingroup rsvp_core
+* @ingroup rsvp
 * @return themed rsvp invites list view response.
 */
-function rsvp_view_invites() {
-  global $user;
+function rsvp_view_invites(&$form_state, $user) {
 
-  $content = '';
-  $invites = _rsvp_get_invites();
+  $connector = new RsvpConnector();
+    
+  $form = array();
+  $title = '';
+
+  // Set the breadcrumb trail.
+  drupal_set_breadcrumb(array(l(t('Home'), NULL), l('My account', 'user/'. $user->uid)));
+  drupal_set_title(check_plain($user->name));
+  
+  $invites = _rsvp_get_invites($user->uid);
 
-  $list = array();
+  $nid2inviteslist = array();
   while ($invite = db_fetch_object($invites)) {
-    $list[$invite->nid][] = l($invite->name, "rsvp/email/". $invite->hash, array('title' => t('View invite')));
+    $nid2inviteslist[$invite->nid][] = $invite;
   }
 
-  foreach ($list as $nid => $links) {
-    $node = node_load($nid);
-    if ($node->nid) {
-      $content .= theme('item_list', $links, t('For: ') . l($node->title, 'node/'. $node->nid, array('title' => t('View this event'))) .' - '. format_date($node->event_start, 'small', '', $node->start_offset));
+  foreach ($nid2inviteslist as $nid => $inviteslist) {
+    $links = array();
+  	$node = node_load($nid);
+
+    if ($node) {
+      $field = _rsvp_getField($node->type);
+      foreach ($inviteslist as $invite) {
+    	$rsvp = rsvp_load($invite->rid);
+        $pos = $connector->get_posByHash($node, $field, $rsvp->startdate);
+        if ($pos >= 0) {
+          $startdate = $connector->get_startdateAsString($node, $field, $pos);
+        }
+        else {
+          $startdate = 'UNKNOWN STARTDATE:' . $rsvp->startdate;	
+        }
+        $links[] = l($invite->name . ' (' . $startdate . ')', "rsvp/email/". $invite->hash . "/view", array('attributes' => array('title' => t('View invitation'))));
+      }   
+    	
+      $title = t('For: ') . l($node->title, 'node/'. $node->nid, array('attributes' => array('title' => t('View this node/event'))));        
     }
     else {
       // node has been deleted
-      $content .= theme('item_list', $links, t('Deleted event(s):'));
+      $title = t('Deleted event(s):');
+      foreach ($inviteslist as $invite) {
+        $links[] = l($invite->name, "rsvp/email/". $invite->hash. "/view", array('attributes' => array('title' => t('View invitation'))));
+      }   
+      
     }
+    
+    $itemlist = theme('item_list', $links, $title);
+    $form['item_list_'.$nid] = array('#value' => $itemlist);
+    
   }
-  if (count($list) == 0) {
-    $content .= '<p>'. t('You have not been invited to any events yet.') .'</p>';
+  
+  
+  if (count($nid2inviteslist) == 0) {
+      $form['content'] = array(
+        '#value' => '<p>'. t('You have not been invited to any events yet.') .'</p>',
+      );      
   }
 
-  return $content;
+  return $form;
 }
 
+
+
 /**
 * Handles the rsvp single invite requests.
 *
+* !Attention!: If someone accesses this page by rsvp/email/hash, the user is 
+* still considered "anonymous" and the default access checks would fail.
+*
 * @ingroup rsvp_core
+* @param $invite The invite object to display.
 * @return themed rsvp invite view response.
 */
-function rsvp_view_invite($hash, $action = NULL) {
+function rsvp_invite_view_form(&$form_state, $invite) {
+  
+  $is_anonymous = user_is_anonymous();
+  	
   global $user;
 
-  $invite = _rsvp_get_invite($hash);
+  $form = array();
+  
+  $connector = new RsvpConnector();
 
-  switch ($action) {
-  default:
-    // check if the invitation exists
-    if (!$invite->rid) {
-      drupal_set_message(t('The invitation you requested does not exist.'));
-      drupal_goto('rsvp');
-    }
-    $rsvp = rsvp_load($invite->rid);
-    $node = node_load($rsvp->nid);
-    // check if the event has been deleted
-    if (!$node->nid) {
-      drupal_set_message(t('The invitation you are trying to view belongs to an event that has been deleted.'));
-      //drupal_goto();
-    }
+  $rsvp = rsvp_load($invite->rid);
+  $node = node_load($rsvp->nid);
+  $field = _rsvp_getField($node->type);
+  // check if the event has been deleted
+  if (!$node->nid) {
+    drupal_set_message(t('The invitation you are trying to view belongs to a node that has been deleted.'));
+    drupal_goto();
+  }
 
-    // This isn't here by mistake: I think we need to log the user action
-    // even if the event has expired.
-    db_query('UPDATE {rsvp_invite} SET invited = 1, received = 1 WHERE hash = \'%s\'', $hash);
-    // show the invitation
-    $content .= rsvp_view($rsvp->rid);
-    // check if the event has expired
-    if (time() > $node->event_end) {
-      drupal_set_message(t('You can no longer respond to this invitation since the event has expired.'));
-    }
-    else {
-      $content .= theme('rsvp_reply', drupal_get_form('rsvp_reply_form', $hash));
+  
+  // Set the breadcrumb trail.
+  drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->title, 'node/'. $node->nid)));
+  drupal_set_title(check_plain('RSVP: ' . $rsvp->name));
+  
+  // This isn't here by mistake: I think we need to log the user action
+  // even if the event has expired.
+  db_query('UPDATE {rsvp_invite} SET invited = 1, received = 1 WHERE hash = \'%s\'', $invite->hash);
+  
+  // show the invitation
+  $form = array_merge_recursive($form, rsvp_view_form($form_state, $rsvp, $node, true));
+  // check if the event has expired
+  $pos = $connector->get_posByHash($node, $field, $rsvp->startdate);
+  if (time() > $connector->get_enddate($node, $field, $pos)) {
+    drupal_set_message(t('You can no longer respond to this invitation since the event has expired.'));
+  }
+  else {
+    
+    $form = array_merge_recursive($form, rsvp_reply_form($form_state, $invite));
 
-      $form = NULL;
-      if (_rsvp_is_invite_viral($invite->rid)) {
-        $form = drupal_get_form('rsvp_attendee_form', $invite->rid);
-      }
-      if (_rsvp_is_invite_message_enabled($invite->rid)) {
-        $form .= '<h2>'. t('You may also message the attendees of this invite using the form below') .':</h2>';
-        $form .= drupal_get_form('rsvp_message_form', $invite->rid, $hash);
-      }
-      if ($form) {
-        $content .= theme('rsvp_invite_action', $form);
-      }
+    if (rsvp_message_hash_access($connector, $invite)) {
+      $form['rsvp_invite_view'][] = array(
+        '#value' => '<h3>' . t('You may also send the attendees of this invite a !message.', array('!message' => l(t('message'), 'rsvp/email/'. $invite->hash .'/message'))) . '</h3>',
+      );
     }
-    $content = theme('rsvp_invite', $invite, $rsvp, $content);
-    break;
+    
+    if (rsvp_user_attendees_viral_access($connector, $invite)) {
+      $form['rsvp_invite_view'][] = array(
+        '#value' => '<h3>' . t('You may also !add attendees to this invite.', array('!add' => l(t('add'), 'rsvp/email/'. $invite->hash .'/attendees'))) . '</h3>',
+      );
 
-  case 'status':
-    // show attendee status
-    $content = rsvp_attendee_status($hash);
-    break;
+    }
 
-  case 'remove':
-    // attempt to remove an attendee
-    $rsvp = rsvp_load($invite->rid);
-    $content = drupal_get_form('rsvp_attendee_confirm_remove', $hash, $rsvp->nid, $rsvp->rid);
-    break;
+    $form = array_merge_recursive($form, rsvp_show_attendees_form($form_state, $rsvp));
+    
+    //if ($form) {
+    //  $content .= theme('rsvp_invite_action', $form);
+    //}
   }
+  //$content = theme('rsvp_invite', $invite, $rsvp, $content);
 
-  return $content;
+  return $form;
 }
 
+
 /**
 * Displays an html formatted rsvp
 *
 * @ingroup rsvp_view
-* @param $rsvp The rsvp to display.
-* @return html formatted view of the requested rsvp instance.
+* @param $node The node object to display.
+* @param $rsvp The rsvp object to display.
+* * @return html formatted view of the requested rsvp instance.
 */
-function rsvp_view($rid) {
-  $rsvp = rsvp_load($rid);
-  $node = node_load($rsvp->nid);
-  if ($node->nid) {
-    $content = theme('rsvp_event', $node);
+function rsvp_view_form(&$form_state, $rsvp, $node = NULL, $embedded = false) {
+    
+  $form = array();
+
+  if (is_null($node)) {
+    $node = node_load($rsvp->nid); 
+  }
+  
+  if ($embedded == false) {
+    // Set the breadcrumb trail.
+    drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->title, 'node/'. $node->nid . '/rsvp')));
+    drupal_set_title(check_plain('RSVP: ' .$rsvp->name));
+  }
+  
+  $field = _rsvp_getField($node->type);
+  $connector = new RsvpConnector();
+  $pos = $connector->get_posByHash($node, $field, $rsvp->startdate);
+  $startdate = $connector->get_startdateAsString($node, $field, $pos);
+
+  //$form['rsvp_view']['header'] = array(
+  //  '#value' => '<h1>' . $rsvp->name . '</h1>',  
+  //);
+  
+  $content = theme('rsvp_event', $node, $startdate);
+  $form['rsvp_view']['output'] = array('#value' => $content);
+
+  if (user_is_anonymous()) {  
+    $content = theme('rsvp_event_anonymous');
+    $form['rsvp_view']['output2'] = array('#value' => $content);
   }
-  $content .= '<h3>'. t('Invite Message') .'</h3>'. $rsvp->invite_text;
+  
+  //$content = '</br><h3>'. t('Invite Message') .'</h3>'. $rsvp->invite_text;
+  $content = $rsvp->invite_text;
+  
+  $output = theme('rsvp', $rsvp, $content);
+  $form['rsvp_view']['output3'] = array('#value' => $output);
 
-  return theme('rsvp', $rsvp, $content);
+  return $form;
 }
 
 /**
 * Displays html formatted attendees of an rsvp instance
 *
 * @ingroup rsvp_view
-* @param $rid The rid of the rsvp instance.
-* @param $controls Boolean that disables attendee control links. Default - enabled..
+* @param $rsvp The rsvp instance.
 * @return html formatted view of the requested invite instance.
 */
-function rsvp_show_attendees($rsvp, $controls = TRUE) {
-  $content = '<h2>'. t('Responses') .'</h2>';
-  $content .= l(t('Download RSVP List'), 'node/'. $rsvp->nid .'/rsvp/'. $rsvp->rid .'/attendees/csv');
-  $content .= '<br /><br />';
-  if ($rsvp->blind && !_rsvp_is_owner($rsvp->rid)) {
-    // for blind rsvps display only totals
-    $totals = _rsvp_attendance_totals($rsvp->rid);
-    foreach ($totals as $key => $value) {
-      if ($value) {
-        $list[] = $key .': '. $value;
-      }
-    }
-    $content .= theme('item_list', $list);
-  }
-  else {
-    // display full attendee info
-    $attendees = _rsvp_get_attendees($rsvp->rid);
-    while ($attendee = db_fetch_object($attendees)) {
-      if ($attendee->uid) {
-        $u = db_fetch_object(db_query("SELECT uid, name FROM {users} WHERE uid = %d", $attendee->uid));
-        $name = l($u->name, 'user/'. $u->uid, array('title' => t('view user')));
-      }
-      else {
-        // hide e-mails for system users
-        $user = user_load(array('uid' => $attendee->uid));
-        $user_name = ($user->uid == 0 ? $attendee->email : $user->name);
-        $name = ($controls ? $user_name : substr($attendee->email, 0, strpos($attendee->email, '@')));
-      }
+function rsvp_show_attendees_form(&$form_state, $rsvp) {
 
-      $links = array();
-      if ($controls) {
-        $links['status'] = array(
-          'title' => t('status'),
-          'href' => 'rsvp/email/'. $attendee->hash .'/status',
-          'attributes' => array('title' => t('view user invite status'))
-        );
-        $links['remove'] = array(
-          'title' => t('remove'), 
-          'href' => 'rsvp/email/'. $attendee->hash .'/remove', 
-          'attributes' => array('title' => t('remove user from rsvp'))
-        );
-        $link = $name .' - '. theme('links', $links);
-      }
-      else {
-        $link = $name;
-      }
+  $form = array();
 
-      if (!$attendee->invited) {
-        $notsent[] = $link;
-      }
+  $are_responses_visible = rsvp_visible_responses_access($rsvp->rid);
+  $are_attendees_visible = rsvp_visible_attendees_access($rsvp->rid);
+  $show_edit_links = (_rsvp_is_owner($rsvp->rid) || user_access('administer rsvp') || user_access('maintain rsvp'));
+  
+  $totals = _rsvp_attendance_totals($rsvp->rid);
 
-      switch ($attendee->response) {
-        case 'none' :
-            $noreply[] = $link;
-          break;
-        case 'yes' :
-            $yes[] = $link;
-          break;
-        case 'no' :
-            $no[] = $link;
-          break;
-        case 'maybe' :
-            $maybe[] = $link;
-          break;
+  $form['rsvp_show_attendees'] = array(
+    '#type' => 'fieldset',
+    '#title' => '<h3>' . t('Responses') . '</h3>',
+  );
+  
+  if ($are_responses_visible) {
+	
+  	
+    if (!$are_attendees_visible) {
+      // for blind rsvps display only totals
+      foreach ($totals as $key => $value) {
+        if ($value) {
+          $list[] = $key .': '. $value;
+        }
       }
+    
+      $itemlist = theme('item_list', $list, NULL);
+      $form['rsvp_show_attendees']['item_list_show_attendees1'] = array('#value' => $itemlist);
+     
     }
+    else {
+      // display full attendee info
+  	
+    	$form['rsvp_show_attendees']['responses2'] = array(
+      '#value' => l(t('Download RSVP List'), 'rsvp/'. $rsvp->rid .'/attendees/csv'),  
+      );
 
-    if ($controls && $notsent) {
-      $title = t('No invitation sent') .' ['. l(t('Send invites'), 'node/'. $rsvp->nid .'/rsvp/'. $rsvp->rid .'/attendees/send', array('title' => t('Send invititations to uninvited users'))) .']';
-      $content .= theme('item_list', $notsent, $title);
-    }
-    $content .= theme('item_list', $noreply, t('No response'));
-    $content .= theme('item_list', $yes, t('Attending'));
-    $content .= theme('item_list', $no, t('Not attending'));
-    $content .= theme('item_list', $maybe, t('Might attend'));
-  }
-
-  return $content;
-}
+      $form['rsvp_show_attendees']['responses3'] = array(
+        '#value' => '<br /><br />',  
+      );
+  	
+      $attendees = _rsvp_get_attendees($rsvp->rid);
+      while ($attendee = db_fetch_object($attendees)) {
+        if ($attendee->uid) {
+          $u = db_fetch_object(db_query("SELECT uid, name FROM {users} WHERE uid = %d", $attendee->uid));
+          $href = 'user/'. $attendee->uid;
+        }
+        else {
+          $href = NULL;
+        }
+        $name = _rsvp_getAttendeeEmail($attendee, false);      
 
-function rsvp_attendees($rid, $hash = NULL, $action = NULL) {
-  $content = '';
-  if (user_access('rsvp newsletters subscribers')) {
-    $content .= rsvp_list_simplenews($rid);
+        $links = array();
+        if ($show_edit_links) {
+          $links['name'] = array(
+            'title' => $name .' - ',
+            'href' => $href,
+          );
+          $links['comment'] = array(
+            'title' => check_plain($attendee->comment),
+          );
+          $links['status'] = array(
+            'title' => t('status'),
+            'href' => 'rsvp/email/'. $attendee->hash .'/status',
+            'attributes' => array('title' => t('view user invite status'))
+          );
+          $links['remove'] = array(
+            'title' => t('remove'), 
+            'href' => 'rsvp/email/'. $attendee->hash .'/remove', 
+            'attributes' => array('title' => t('remove user from rsvp'))
+          );
+          $link = theme('links', $links);
+        }
+        else {
+          $link = check_plain($name) . ' - ' . check_plain($attendee->comment);
+        }
+
+        if (!$attendee->invited) {
+          $notsent[] = $link;
+        }
+
+        switch ($attendee->response) {
+          case 'yes' :
+              $yes[] = $link;
+            break;
+          case 'no' :
+              $no[] = $link;
+            break;
+          case 'maybe' :
+              $maybe[] = $link;
+            break;
+          case 'none' :
+          default:
+              $noreply[] = $link;
+          break;
+        }
+      }
+
+      if ($show_edit_links && $notsent) {
+        $title = t('No invitation sent') .' ['. l(t('Send invites'), 'rsvp/'. $rsvp->rid .'/attendees/send', array('attributes' => array('title' => t('Send invititations to uninvited users')))) .']';
+      
+        $itemlist = theme('item_list', $notsent, $title);
+        $form['rsvp_show_attendees']['item_list_show_attendees2'] = array('#value' => $itemlist);
+      }
+    
+      $itemlist = theme('item_list', $noreply, t('No response ') . $totals['No Response']);
+      $form['rsvp_show_attendees']['item_list_show_attendees3'] = array('#value' => $itemlist);
+
+      $itemlist = theme('item_list', $yes, t('Attending ') . $totals['Attending']);
+      $form['rsvp_show_attendees']['item_list_show_attendees4'] = array('#value' => $itemlist);
+    
+      $itemlist = theme('item_list', $no, t('Not attending ') . $totals['Not attending']);
+      $form['rsvp_show_attendees']['item_list_show_attendees5'] = array('#value' => $itemlist);
+    
+      $itemlist = theme('item_list', $maybe, t('Might attend ') . $totals['Might attend']);
+      $form['rsvp_show_attendees']['item_list_show_attendees6'] = array('#value' => $itemlist);
+    }
   }
-  if (user_access('rsvp system users')) {
-    $content .= rsvp_list_roles($rid);
+  else {
+  	if ($rsvp->response_blind == RSVP_RESPONSE_SHOWWHENREPLIED) {
+  	  $form['rsvp_show_attendees']['responses4'] = array(
+        '#value' => 'Responses by other attendees will be visible as soon as you replied.',  
+      );
+  	}
+  	
   }
-  $content .= drupal_get_form('rsvp_attendee_form', $rid);
-  $content .= rsvp_show_attendees(rsvp_load($rid));
-  return $content;
+  
+  return $form;
 }
 
+
+
 /**
 * Displays html formatted attendee reply status for an invite
 *
 * @ingroup rsvp_view
-* @param $hash The hash value of the invite.
+* @param $invite The invite object.
 * @return html formatted view of the requested invite status.
 */
-function rsvp_attendee_status($hash) {
-  $invite = _rsvp_get_invite($hash);
-  $list[] = ($invite->invited ? t('Attendee has been invited') : t('Attendee has not been invited'));
-  $list[] = ($invite->received ? t('Attendee has viewed the invitation') : t('Attendee has not viewed the invitation'));
-  $list[] = t('Attendee response: %response', array('%response' => $invite->response));
+function rsvp_invite_status_attendee_form(&$form_state, $invite) {
+
+  $form = array();
+  
+  $rsvp = rsvp_load($invite->rid);
+  
+  // Set the breadcrumb trail.
+  drupal_set_breadcrumb(array(l(t('Home'), NULL), l($rsvp->name, 'rsvp/'. $rsvp->rid . '/attendees')));
+  drupal_set_title(check_plain('RSVP: ' . $rsvp->name));
+  
+  $list[] = ($invite->invited ? t('Attendee has been sent an invitation.') : t('Attendee has not been sent an invitation.'));
+  $list[] = ($invite->received ? t('Attendee has viewed the invitation.') : t('Attendee has not viewed the invitation.'));
+  if ($invite->response)
+    $list[] = t('Attendee response: %response', array('%response' => $invite->response));
 
-  return theme('item_list', $list, $invite->email);
+    
+  $output = theme('item_list', $list, _rsvp_getAttendeeEmail($invite));
+  $form['list'] = array('#value' => $output);
+
+  return $form;
 }
 
 /**
 * Displays the rsvp attendee editing form
 *
 * @ingroup rsvp_form
-* @param $rid The id of the rsvp instance to edit.
+* @param $invite The invite object.
 * @return html formatted rsvp attendee edit form.
 */
-function rsvp_attendee_form($rid) {
-  $rsvp = rsvp_load($rid);
-  drupal_set_title($rsvp->name);
-  $form['invite_list'] = array(
-      '#type' => 'textarea',
-      '#title' => t('Add Attendees'),
-      '#default_value' => '',
-      '#cols' => 60,
-      '#rows' => 5,
-      '#description' => t('Enter email addresses or usernames each in a separate line.')
-      );
-  $form['rid'] = array(
-    '#type' => 'hidden',
-    '#value' => $rid,
+function rsvp_attendee_hash_form(&$form_state, $invite ) {
+	
+  $rsvp = rsvp_load($invite->rid);
+  $node = node_load($rsvp->nid);
+	
+  if (!$node->nid) {
+    drupal_set_message(t('The invitation you requested belongs to a node that has been deleted.'));
+    drupal_goto();
+  }  
+	
+  return rsvp_attendee_form($form_state, $rsvp, $node);
+}
+
+/**
+* Displays the rsvp attendee editing form
+*
+* @ingroup rsvp_form
+* @param $rsvp The rsvp object to edit.
+* @param $node The node object to edit.
+* @return html formatted rsvp attendee edit form.
+*/
+function rsvp_attendee_form(&$form_state, $rsvp, $node = NULL) {
+  
+  $form = array();
+
+  $owner = _rsvp_is_owner($rsvp->rid);
+  
+  if (is_null($node)) {
+    $node = node_load($rsvp->nid);
+  }
+
+  // Set the breadcrumb trail.
+  drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->title, 'node/'. $node->nid . '/rsvp')));
+  drupal_set_title(check_plain('RSVP: ' . $rsvp->name));
+
+  if ($owner && user_access('rsvp newsletters subscribers')) {
+    $form = array_merge_recursive($form, rsvp_list_simplenews_form($form_state, $rsvp));
+  }
+  if ($owner && user_access('rsvp system users')) {
+    $form = array_merge_recursive($form, rsvp_list_roles_form($form_state, $rsvp));
+  }
+
+  if ($owner || _rsvp_is_invite_viral($rsvp->rid)) {
+    $form = array_merge_recursive($form, rsvp_add_attendees_form($form_state, $rsvp));
+  }
+  
+  $form = array_merge_recursive($form, rsvp_show_attendees_form($form_state, $rsvp));
+
+  //$form_state['redirect'] = 'node/'. $node->nid .'/rsvp';
+  
+  return $form;
+}
+
+
+
+/**
+* Displays the rsvp attendee editing form where users can add addtional email addresses
+*
+* @ingroup rsvp_form
+* @param $rsvp The rsvp object to edit.
+* @return html formatted rsvp attendee edit form.
+*/
+function rsvp_add_attendees_form(&$form_state, $rsvp) {
+
+  $form = array();
+
+  $form['rsvp_add_attendees'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('People you like to invite'),
+  );
+  
+  $form['rsvp_add_attendees']['invite_list'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Add Attendees'),
+    '#default_value' => check_plain(''),
+    '#cols' => 60,
+    '#rows' => 3,
+    '#description' => t('Enter email addresses or usernames each in a separate line.'),
   );
 
-  $form['submit'] = array(
+  $form['rsvp_add_attendees']['submit'] = array(
       '#type' => 'submit',
-      '#value' => t('Send Invites'),
-      );
+      '#value' => t('Add'),
+      '#submit' => array('rsvp_add_attendees_form_submit'),
+      '#validate' => array('rsvp_add_attendees_form_validate'),
+      '#description' => t('Adds persons to the list of attendees.'),
+  );
 
+  
+  $form['rsvp_add_attendees']['rid'] = array('#type' => 'value', '#value' => $rsvp->rid);
+  
   return $form;
 }
 
-function rsvp_attendee_form_validate($form, &$form_state) {
+
+function rsvp_add_attendees_form_validate($form, &$form_state) {
   if (!strlen(preg_replace('/\s+/', '', $form_state['values']['invite_list']))) {
-    drupal_set_message(t('Attendees list is empty.'), 'error');
+    form_set_error('', t('Attendees list is empty.'));      
   }
 }
 
-function rsvp_attendee_form_submit($form, &$form_state) {
+function rsvp_add_attendees_form_submit($form, &$form_state) {
+
+  $invitee_list = $form_state['values']['invite_list'];
+  $rid = $form_state['values']['rid'];
+
+  $send_immediatly = !rsvp_visible_responses_access($rid);
+  
+  _rsvp_add_attendees($rid, $invitee_list, $send_immediatly);
+}
+
+
+function _rsvp_add_attendees($rid, $invite_list, $send_rsvp = true) {
+
   $content = '';
   // attempt to add the list of e-mails
-  $emails = rsvp_set_invites(trim($form_state['values']['invite_list']), $form_state['values']['rid']);
-  // send RSVPs
-  $status = _rsvp_mail_rsvp($form_state['values']['rid']);
-  // theme the output
+  $emails = rsvp_set_invites(trim($invite_list), $rid);
+  $status = array();
+  
+  if ($send_rsvp == true) {
+    // send RSVPs
+    $status = _rsvp_send_multiple_invitations($rid);
+  }
+
   $content .= theme('rsvp_send_status', array_merge($emails, $status));
   drupal_set_message($content);
+  
 }
 
-function rsvp_attendee_confirm_remove($hash, $nid, $rid) {
-  $invite = _rsvp_get_invite($hash);
-  $form['nid'] = array(
-    '#type' => 'hidden',
-    '#value' => $nid,
-  );
-  $form['rid'] = array(
-    '#type' => 'hidden',
-    '#value' => $rid,
-  );
-  $form['hash'] = array(
-    '#type' => 'hidden',
-    '#value' => $hash,
-  );
+
+
+function rsvp_invite_remove_attendee_form(&$form_state, $invite) {
+
+  $form = array();
+
+  $rsvp = rsvp_load($invite->rid);
+  //$node = node_load($rsvp->nid);
+  
+  // Set the breadcrumb trail.
+  drupal_set_breadcrumb(array(l(t('Home'), NULL), l($rsvp->name, 'rsvp/'. $rsvp->rid . '/attendees')));
+  drupal_set_title(check_plain('RSVP: ' . $rsvp->name));
+  
+  $form['hash'] = array('#type' => 'value', '#value' => $invite->hash);
+  
   return confirm_form($form, 
-    t('Are you sure you want to remove?'),
-    'node/'. $nid .'/rsvp/'. $rid .'/attendees',
+    t('Are you sure you want to remove attendee ') . theme('placeholder', _rsvp_getAttendeeEmail($invite)) . '?',
+    'rsvp/'. $rsvp->rid .'/attendees',
     t('Removing an attendee will delete their responses and remove their access to their invitations to this RSVP.'),
-    t('Remove Attendee'), t('Cancel')
+    t('Remove Attendee'), 
+    t('Cancel')
   );
 }
 
-function rsvp_attendee_confirm_remove_submit($form, &$form_state) {
-  $invite = _rsvp_get_invite($form_state['values']['hash']);
-  // hide e-mails for system users
-  $user = user_load(array('uid' => $invite->uid));
-  $name = ($user->uid == 0 ? $invite->email : $user->name);
-  drupal_set_message(t('The attendee !name has been removed.', array('!name' => theme('placeholder', $name))));
-  _rsvp_remove_attendee($form_state['values']['hash']);
-  return 'node/'. $form_state['values']['nid'] .'/rsvp/'. $form_state['values']['rid'] .'/attendees';
+function rsvp_invite_remove_attendee_form_submit($form, &$form_state) {
+
+  if ($form_state['values']['confirm']) {
+	$invite = _rsvp_get_invite_by_hash($form_state['values']['hash']);
+    $rsvp = rsvp_load($invite->rid);
+    $name = _rsvp_getAttendeeEmail($invite);
+    drupal_set_message(t('The attendee !name has been removed.', array('!name' => theme('placeholder', $name))));
+    _rsvp_remove_attendee($form_state['values']['hash']);
+    
+  }
+  
+  $form_state['redirect'] = 'rsvp/'. $rsvp->rid .'/attendees';
+  
+  return;
 }
 
 /**
  * Callback to display an attendee list as CSV file
  *  - Copied from CiviCRM (which was copied from phpMyAdmin) so it should be robust
- */
-function rsvp_attendees_csv($rid) {
+ * @param $node The node object to edit.
+ *
+ *  */
+function rsvp_attendees_csv_form(&$form_state, $rsvp) {
+
+  $form = array();
+  	
   //fields to export
   $field_list = array( 'response', 'email', 'invited', 'received' );
 
-  $rsvp = rsvp_load($rid);
+  $rid = $rsvp->rid;
   $attendees = _rsvp_get_attendees($rid);
   $attendee = db_fetch_object($attendees);
   $header = array();
@@ -692,7 +1392,7 @@
     if (in_array( $key, $field_list ))
       $header[]  = $key;
   }
-
+  
   $filename = str_replace(' ', '_', $rsvp->name) .'_'. date("Y-m-d") .'.csv';
 
   $now       = gmdate('D, d M Y H:i:s') .' GMT';
@@ -759,6 +1459,9 @@
             $schema_insert .= '';
           }
           else if ($value == '0' || $value != '') {
+            if ($j == 'email') {
+              $value = _rsvp_getAttendeeEmail($row, false);
+            }
             // loic1 : always enclose fields
             $value = ereg_replace("\015(\012)?", "\012", $value);
             if ($enclosed == '') {
@@ -791,87 +1494,123 @@
       ++$i;
 
   } // end for
+
+  drupal_goto('rsvp/'. $rsvp->rid .'/attendees');
+  return $form;
+  
 }
 
 /**
  * Callback to send invitations to users already
  * in the invitation list.
+ * 
+ * @param $rsvp The rsvp object to send the message to.
  *
  */
-function rsvp_attendees_send_invites($rid, $destination = NULL) {
+function rsvp_attendees_send_invites_form(&$form_state, $rsvp) {
+
   // send RSVPs
-  $status = _rsvp_mail_rsvp($rid);
+  $status = _rsvp_send_multiple_invitations($rsvp->rid);
   // theme the output
   $content = theme('rsvp_send_status', $status);
   drupal_set_message($content);
-  if ($destination != NULL) {
-    drupal_goto($destination);
-  }
+  
+  drupal_goto('rsvp/'. $rsvp->rid .'/attendees');
 }
 
 /**
 * Displays the rsvp send list message form.
 *
 * @ingroup rsvp_form
-* @param $rid The id of the rsvp to send the message to.
+* @param $rsvp The rsvp object to send the message to.
+* @param $invite The invite object.
 * @return html formatted rsvp send list message form.
 */
-function rsvp_message_form($rid, $hash = NULL) {
-  $rsvp = rsvp_load($rid);
-  drupal_set_title($rsvp->name);
+function rsvp_message_hash_form(&$form_state, $invite) {
+  
+  $rsvp = rsvp_load($invite->rid);
+  $node = node_load($rsvp->nid);
+    
+  if (!$node->nid) {
+    drupal_set_message(t('The invitation you requested belongs to a node that has been deleted.'));
+    drupal_goto();
+  }  
+    
+  return rsvp_message_form($form_state, $rsvp, $node );
+	
+}
+
+
+/**
+* Displays the rsvp send list message form.
+*
+* @ingroup rsvp_form
+* @param $rsvp The rsvp object to send the message to.
+* @param $node The node object of the rsvp.
+* @return html formatted rsvp send list message form.
+*/
+function rsvp_message_form(&$form_state, $rsvp, $node = NULL, $invite = NULL) {
 
   $form = array();
-  $form['status'] =  array(
-       '#type' => 'select',
-       '#title' => t('Message audience'),
-       '#default_value' => 'all',
-       '#options' => array('all' => t('Entire RSVP List'), 'yes' => t('Attending'), 'no' =>  t('Not attending'), 'maybe' =>  t('Might attend'), 'none' =>  t('No reply')),
-       );
-  $form['subject'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Message Subject'),
-      '#default_value' => '',
-      '#size' => 40,
-      '#maxlength' => 40,
-      '#description' => t('This is the subject for your email message')
-      );
-  $form['body'] = array(
-      '#type' => 'textarea',
-      '#title' => t('Message Body'),
-      '#default_value' => '',
-      '#cols' => 60,
-      '#rows' => 5,
-      '#description' => t('This is the body of the email message')
-      );
-  $form['rid'] = array(
-      '#type' => 'hidden',
-      '#value' => $rid
-      );
-  if (!is_null($hash)) {
-    $form['hash'] = array(
-        '#type' => 'hidden',
-        '#value' => $hash
-      );
+	
+  if (is_null($node)) {
+  	$node = node_load($rsvp->nid);
+  }
+  
+  // Set the breadcrumb trail.
+  drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->title, 'node/'. $node->nid . '/rsvp')));
+  drupal_set_title(check_plain('RSVP: ' . $rsvp->name));
+  
+  $form['rsvp_message']['status'] =  array(
+    '#type' => 'select',
+    '#title' => t('Message audience'),
+    '#default_value' => RSVP_ATT_ALL,
+    '#options' => array(RSVP_ATT_ALL => t('Entire RSVP List'), RSVP_ATT_YES => t('Attending'), RSVP_ATT_NO =>  t('Not attending'), RSVP_ATT_MAYBE =>  t('Might attend'), RSVP_ATT_NONE =>  t('No reply')),
+  );
+  $form['rsvp_message']['subject'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Message Subject'),
+    '#default_value' => check_plain(''),
+    '#size' => 40,
+    '#maxlength' => 40,
+    '#description' => t('This is the subject for your email message')
+  );
+  $form['rsvp_message']['body'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Message Body'),
+    '#default_value' => check_markup(''),
+    '#cols' => 60,
+    '#rows' => 5,
+    '#description' => t('This is the body of the email message')
+  );
+  $form['rsvp_message']['rid'] = array('#type' => 'value', '#value' => $rsvp->rid);
+  if (!is_null($invite)) {
+    $form['rsvp_message']['hash'] = array('#type' => 'value', '#value' => $invite->hash);
   }
 
-  $form['submit'] = array(
-      '#type' => 'submit',
-      '#value' => t('Send Message'),
-      );
+  $form['rsvp_message']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Send Message'),
+    '#submit' => array('rsvp_message_form_submit'),
+  );
 
   // make sure that we won't send to none:
-  $attendees = _rsvp_get_attendees($rid);
-  if (!db_num_rows($attendees)) {
+  $attendees_count = db_result(_rsvp_get_attendees($rsvp->rid, RSVP_ATT_ALL, TRUE));
+  
+  if (!$attendees_count) {
     drupal_set_message(t('No invitees in this RSVP.'));
-    $form['submit']['#disabled'] = TRUE;
+    $form['rsvp_message']['submit']['#disabled'] = TRUE;
   }
 
   return $form;
 }
 
 function rsvp_message_form_submit($form, &$form_state) {
-  global $user;
-  $status = rsvp_send_message($form_state['values']);
+  $status = rsvp_send_message($form_state['values']['rid'], 
+                              $form_state['values']['status'],
+                              $form_state['values']['subject'],
+                              $form_state['values']['body'],
+                              $form_state['values']['hash']);
   $content = theme('rsvp_send_status', $status);
   drupal_set_message($content);
 }
@@ -881,68 +1620,69 @@
 * Displays html formatted invite reply status information for a user's invite
 *
 * @ingroup rsvp_view
-* @param $hash The hash value of the invite.
+* @param $invite The invite object.
 * @return html formatted view of the requested invite status.
 */
-function rsvp_reply_form($hash) {
-  $invite = _rsvp_get_invite($hash);
-  $responses = array('yes' => t('Yes'), 'no' => t('No'), 'maybe' => t('Maybe'));
-  if ($invite->response == 'none') {
-    $responses['none'] = t('None');
+function rsvp_reply_form($form_state, $invite) {
+
+  $responses = array(RSVP_ATT_YES => t('Yes'), RSVP_ATT_NO => t('No'), RSVP_ATT_MAYBE => t('Maybe'));
+  if ($invite->response == RSVP_ATT_NONE) {
+    $responses[RSVP_ATT_NONE] = t('None');
   }
 
   $form = array();
-  $form['invite_reply'] = array(
-      '#type' => 'select',
-      '#title' => t('Your Reply'),
-      '#default_value' => $invite->response,
-      '#options' => $responses,
-      '#description' => t('Select your response to the invitation here.')
-      );
-  $form['hash'] = array(
-      '#type' => 'hidden',
-      '#value' => $hash
-      );
+  
+  $form['rsvp_reply'] = array(
+    '#type' => 'fieldset',
+    '#title' => t(''),
+    '#prefix' => '<div class="rsvpreplybox">',
+    '#suffix' => '</div>',
+  );  
+  
+  $form['rsvp_reply']['invite_reply'] = array(
+    '#type' => 'select',
+    '#title' => t('Your Reply'),
+    '#default_value' => check_plain($invite->response),
+    '#options' => $responses,
+    '#description' => t('Select your response to the invitation here.')
+  );
+  $form['rsvp_reply']['rsvp_comment'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Comment'),
+    '#default_value' => check_plain($invite->comment),
+    '#cols' => 60,
+    '#rows' => 5,
+    '#description' => t('Add a comment to your response.')
+  );
+  
+  $form['rsvp_reply']['hash'] = array('#type' => 'value', '#value' => $invite->hash);
 
-  $form['submit'] = array(
-      '#type' => 'submit',
-      '#value' => t('Reply')
-      );
+  $form['rsvp_reply']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Reply'),
+    '#submit' => array('rsvp_reply_form_submit'),
+  );
 
   return $form;
 }
 
 function rsvp_reply_form_submit($form, &$form_state) {
   global $user;
-  drupal_set_message('Your response was saved.', 'status');
-  db_query('UPDATE {rsvp_invite} SET response = \'%s\', invited = 1, received = 1 WHERE hash = \'%s\'', $form_state['values']['invite_reply'], $form_state['valued']['hash']);
-  drupal_goto('user/'. $user->uid .'/rsvp');
+  drupal_set_message('Your response has been saved.', 'status');
+  db_query('UPDATE {rsvp_invite} SET response = \'%s\', comment = \'%s\', invited = 1, received = 1 WHERE hash = \'%s\'', $form_state['values']['invite_reply'], $form_state['values']['rsvp_comment'], $form_state['values']['hash']);
+
 }
 
 
-/**
- * @defgroup rsvp_data_functions functions for rsvp data manipulation.
- */
-
-function rsvp_addedit($edit) {
-  // if the rsvp already exists
-  if ($edit['rid']) {
-   return rsvp_update($edit); 
-  }
-  else {
-    $rid = rsvp_create($edit); 
-    drupal_goto('node/'. $edit['nid'] .'/rsvp/'. $rid .'/attendees');
-  }
-}
 
 /**
 * Creates a new rsvp
 *
 * @ingroup rsvp_functions
-* @param $edit The post data of the create rsvp form.
-* @return int key id of the rsvp instance or -1 on failure.
+* @param $form_state The post data of the create rsvp form.
+* @return int key id of the rsvp instance or false on failure.
 */
-function rsvp_create($edit) {
+function rsvp_create(&$form_state) {
   global $user;
 
   $fields[] = 'uid';
@@ -953,26 +1693,26 @@
   $vals[] = time();
   $markers[] = "%d";
 
-  foreach (array('name', 'invite_text', 'invite_list', 'blind', 'list_email', 'allow_invite', 'nid') as $key) {
+  $fields[] = 'startdate';
+  $vals[] = $form_state['values']['startdate'];
+  $markers[] = "%d";
+  
+  foreach (array('name', 'invite_text', 'invite_list', 'response_blind', 'attendees_visible', 'list_email', 'allow_invite', 'nid') as $key) {
     if ($key != 'invite_list') {
       $fields[] = $key;
-      $vals[] = $edit[$key];
+      $vals[] = $form_state['values'][$key];
       $markers[] = "'%s'";
     }
   }
 
-  $rid = db_last_insert_id('rsvp');
-  $fields[] = 'rid';
-  $vals[] = $rid;
-  $markers[] = "%d";
-
   $sql = 'INSERT INTO {rsvp} ('. implode(", ", $fields) .') VALUES ('. implode(", ", $markers) .')';
-
   if (db_query($sql, $vals)) {
+    $rid = db_last_insert_id('rsvp', 'rid');
+  
     return $rid;
   }
   else {
-    drupal_set_message(t('There was an error creating the RSVP. Please try again'));
+    drupal_set_message(t('There was an error creating the RSVP. Please try again'), 'error');
     return FALSE;
   }
 }
@@ -981,23 +1721,26 @@
 * Updates an rsvp
 *
 * @ingroup rsvp_functions
-* @param $edit The post data of the update rsvp form.
+* @param $form_state The post data of the update rsvp form.
 * @return boolean true on success.
 */
-function rsvp_update($edit) {
+function rsvp_update(&$form_state) {
+  
+  $rid = $form_state['values']['rid'];
+
+  if (!$rid) {
+    return FALSE;
+  }
+  
   $fields[] = 'timestamp = %d';
   $vals[] = time();
 
-  foreach (array('name', 'invite_text', 'blind', 'list_email', 'allow_invite') as $key) {
+  $fields[] = 'startdate = %d';
+  $vals[] = $form_state['values']['startdate'];
+  
+  foreach (array('name', 'invite_text', 'response_blind', 'attendees_visible', 'list_email', 'allow_invite') as $key) {
     $fields[] = $key ." = '%s'";
-    $vals[] = $edit[$key];
-  }
-
-  if (!$edit['rid']) {
-    return FALSE;
-  }
-  else {
-    $vals[] = $edit['rid'];
+    $vals[] = $form_state['values'][$key];
   }
 
   $vals[] = $rid;
@@ -1009,7 +1752,7 @@
     return TRUE;
   }
   else {
-    drupal_set_message(t('There was an error updating the RSVP.'));
+    drupal_set_message(t('There was an error updating the RSVP.'), 'error');
     return FALSE;
   }
 }
@@ -1018,70 +1761,129 @@
 * Displays the rsvp editing form
 *
 * @ingroup rsvp_form
-* @param $rid The id of the rsvp instance to edit.
+* @param $node The node we want to edit/create the rsvp on.
+* @param $rsvp The rsvp instance to edit.
 * @return html formatted rsvp edit form.
 */
-function rsvp_addedit_form($nid = NULL, $rid = NULL) {
-  if (!is_null($rid)) {
-    $rsvp = rsvp_load($rid);
-    drupal_set_title($rsvp->name);
+function rsvp_addedit_form(&$form_state, $node = NULL, $rsvp = NULL) {
+    
+  $operation = 'add';
+	
+  if (!is_null($rsvp)) {
+    $operation = 'edit';
+  	drupal_set_title(check_plain('RSVP: ' . $rsvp->name));
   }
   else {
+    drupal_set_title(t('Create RSVP for node "%title"', array('%title' => $node->title)));
     $rsvp = new stdClass();
   }
 
+  if (is_null($node)) {
+  	$node = node_load($rsvp->nid); 
+  }
+  
+  // Set the breadcrumb trail.
+  drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->title, 'node/'. $node->nid . '/rsvp')));
+  
+  $form = array();
+  $fields = array();
+  
+  $connector = new RsvpConnector();
+  
+  
+  
+  $field = _rsvp_getField($node->type);
+  
   $form['name'] = array(
-      '#type' => 'textfield',
-      '#title' => t('RSVP Name'),
-      '#default_value' => $rsvp->name,
-      '#size' => 40,
-      '#maxlength' => 40,
-      '#description' => t('This is the name of your RSVP.')
-      );
+    '#type' => 'textfield',
+    '#title' => t('RSVP Title'),
+    '#default_value' => check_plain($node->title),
+    '#size' => 80,
+    '#maxlength' => 128,
+    '#description' => t('This is the title of your RSVP. Default is the node title.'),
+  );
+
+  if ($connector->hasMultipleFields()) {
+
+    $count = $connector->get_datecount($node, $field);
+    //iterate through all specified enddates (in case of repeating dates)
+    for ($i = 0; $i < $count; $i++) {
+        $key = $connector->get_startdate($node, $field, $i);
+        $value = $connector->get_startdateAsString($node, $field, $i);
+        $fields[$key] = $value;
+    }
+
+    $form['rsvp_field'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Selected field'),
+    );
+    
+    $form['rsvp_field']['field'] = array(
+      '#type' => 'item',
+      '#title' => t('Field name'),
+      '#value' => t($field),
+    );
+
+    $form['rsvp_field']['startdate'] = array(
+      '#type' => 'select',
+      '#title' => t('Event Start'),
+      '#required' => TRUE,
+      '#options' => array_map('check_plain', $fields),
+      '#default_value' => check_plain(isset($rsvp->startdate) ? $rsvp->startdate : 0),
+      '#description' => t('select one of the available start dates to be used as rsvp start date.'),
+    );
+  }
+  
   $form['invite_text'] = array(
-      '#type' => 'textarea',
-      '#title' => t('RSVP Message'),
-      '#default_value' => $rsvp->invite_text,
-      '#cols' => 60,
-      '#rows' => 10,
-      '#description' => t('This text will be sent to the people you invite.')
-      );
-  $form['blind'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Hide attendees'),
-      '#return_value' => 1,
-      '#default_value' => $rsvp->blind,
-      '#description' => t('Prevent attendees from seeing who else is on the list.')
-      );
+    '#type' => 'textarea',
+    '#title' => t('RSVP Message'),
+    '#default_value' => check_markup(!empty($rsvp->invite_text) ? $rsvp->invite_text : ' ' ),
+    '#cols' => 60,
+    '#rows' => 10,
+    '#description' => t('This text will be sent to the people you invite.')
+  );
+  $response_blind = array(RSVP_RESPONSE_SHOW => t('Show responses'), RSVP_RESPONSE_HIDE => t('Hide responses always'), RSVP_RESPONSE_SHOWWHENREPLIED => t('Hide responses until replied'));  
+  $form['response_blind'] = array(
+    '#type' => 'select',
+    '#title' => t('Show responses'),
+    '#required' => TRUE,
+    '#options' => array_map('check_plain', $response_blind),
+    '#default_value' => (isset($rsvp->response_blind) ? $rsvp->response_blind : RSVP_RESPONSE_SHOW),
+    '#description' => t('Prevent attendees from seeing any response information.'),
+  );
+  $attendees_visible = array(RSVP_ATTENDEE_SHOW => t('Show attendee names'), RSVP_ATTENDEE_HIDE => t('Hide attendee names'));  
+  $form['attendees_visible'] = array(
+    '#type' => 'select',
+    '#title' => t('Show attendees'),
+    '#required' => TRUE,
+    '#options' => array_map('check_plain', $attendees_visible),
+    '#default_value' => (isset($rsvp->attendees_visible) ? $rsvp->attendees_visible : RSVP_ATTENDEE_HIDE),
+    '#description' => t('Prevent attendees from seeing who else is on the invitation list. Field "Show responses" has precedence.'),
+  );
+  
   $form['list_email'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Allow list email'),
-      '#return_value' => 1,
-      '#default_value' => $rsvp->list_email,
-      '#description' => t('Allow attendees to send messages to the people invited to your RSVP.')
-      );
+    '#type' => 'checkbox',
+    '#title' => t('Allow to send messages to attendees'),
+    '#return_value' => 1,
+    '#default_value' => $rsvp->list_email,
+    '#description' => t('Allow attendees to send messages to the people invited to your RSVP.')
+  );
   $form['allow_invite'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Allow attendee invites'),
-      '#return_value' => 1,
-      '#default_value' => $rsvp->allow_invite,
-      '#description' => t('Allow attendees to invite more people to the event')
-      );
-  $form['rid'] = array(
-      '#type' => 'hidden',
-      '#value' => $rsvp->rid
-      );
-  $form['nid'] = array(
-      '#type' => 'hidden',
-      '#value' => $nid
-      );
+    '#type' => 'checkbox',
+    '#title' => t('Allow attendee invites'),
+    '#return_value' => 1,
+    '#default_value' => $rsvp->allow_invite,
+    '#description' => t('Allow attendees to invite more people to the event')
+  );
+  $form['rid'] = array('#type' => 'value', '#value' => $rsvp->rid);
+  $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
 
   $form['update'] = array(
-      '#type' => 'submit',
-      '#value' => t('Submit'),
-      '#name' => 'op'
-      );
-  if ($rid) {
+    '#type' => 'submit',
+    '#value' => t('Submit'),
+    '#name' => 'op'
+  );
+  if ($operation == 'edit') {
     $form['delete'] = array(
         '#type' => 'submit',
         '#value' => t('Delete'),
@@ -1096,20 +1898,49 @@
 *
 * @ingroup rsvp_form
 * @param $form_id The id of the form submitted.
-* @param $edit The $edit array.
-* @return path a path to redirect after the form submission.
 */
 function rsvp_addedit_form_submit($form, &$form_state) {
-  if ($form_state['values']['op'] == t('Delete')) {
-    return 'node/'. $form_state['values']['nid'] .'/rsvp/'. $form_state['values']['rid'] .'/delete';
+  
+  $nid = $form_state['values']['nid'];
+  $rid = $form_state['values']['rid'];
+  $op = $form_state['values']['op'];
+  
+  if (!is_numeric($nid)) { 
+    drupal_set_message(t('Node %node is not a valid type.', array('%node' => $nid)), 'error');
+    $form_state['redirect'] = 'node/'. $nid .'/rsvp';
+    return;
   }
-  elseif ($form_state['values']['op'] == t('Submit')) {
-    rsvp_addedit($edit);
-    return 'node/'. $form_state['values']['nid'] .'/rsvp/'. $form_state['values']['rid'] .'/view';
+  
+  if (!is_null($rid) && !is_numeric($rid)) { 
+    drupal_set_message(t('Rsvp %rid is not a valid type.', array('%rid' => $rid)), 'error');
+    $form_state['redirect'] = 'node/'. $nid .'/rsvp';
+    return;
+  }
+  
+  if ($op == t('Delete')) {
+    $form_state['redirect'] = 'rsvp/'. $rid .'/delete';
+    return;
+  }
+  elseif ($op == t('Submit')) {
+    if (!is_null($rid)) {
+      rsvp_update($form_state); 
+    }
+    else {
+      $rid = rsvp_create($form_state); 
+      if ($rid != false) {
+        drupal_set_message(t('New RSVP has been created successfully. Continue adding attendees.'));
+        $form_state['redirect'] = 'rsvp/'. $rid .'/attendees';
+        return;
+      }
+    }
+    
+    $form_state['redirect'] = 'node/'. $nid . '/rsvp';
+    return;
   }
 }
 
 
+
 /**
 * Deletes an rsvp
 *
@@ -1118,6 +1949,12 @@
 * @return boolean true on success.
 */
 function rsvp_delete($rid) {
+
+  if (is_null($rid) || !is_numeric($rid)) { 
+    drupal_set_message(t('Rsvp %rid is not a valid type.', array('%rid' => $rid)), 'error');
+    return RSVP_ERROR_DELETE_RSVP;
+  }
+    
   if (db_query('DELETE FROM {rsvp} WHERE rid = %d', $rid)) {
     if (db_query('DELETE FROM {rsvp_invite} WHERE rid = %d', $rid)) {
       return RSVP_DELETED;
@@ -1130,255 +1967,682 @@
     return RSVP_ERROR_DELETE_RSVP;
   }
 }
+
 /**
 * Displays the rsvp delete are you sure form
 *
 * @ingroup rsvp_form
-* @param $rsvp The rsvp instance to confirm deletion for.
+* @param $rsvp The rsvp object to confirm deletion for.
 * @return html formatted rsvp delete confirmation form.
 */
-function rsvp_delete_form($rid) {
-  $rsvp = rsvp_load($rid);
-  if (!$rsvp->rid) {
-    drupal_set_message(t('The rsvp you requested does not exist.'));
-    drupal_goto('rsvp/manage');
-  }
+function rsvp_delete_form(&$form_state, $rsvp) {
+  global $user;
 
   $form = array();
-  $form['rid'] = array(
-    '#type' => 'hidden',
-    '#value' => $rsvp->rid,
-  );
-  $form['nid'] = array(
-    '#type' => 'hidden',
-    '#value' => $rsvp->nid,
-  );
+
+  $form['rid'] = array('#type' => 'value', '#value' => $rsvp->rid);
+  $form['nid'] = array('#type' => 'value', '#value' => $rsvp->nid);
+
   return confirm_form($form,
-      t('Are you sure you want to delete %name?', array('%name' => $rsvp->name)),
-      'rsvp/'. check_url(arg(1)) .'/edit',
+      t('Are you sure you want to delete RSVP %name?', array('%name' => $rsvp->name)),
+      'rsvp/' . $rsvp->rid . '/edit',
       t('This action cannot be undone.'),
-      t('Delete'), t('Cancel'));
+      t('Delete'), 
+      t('Cancel'));
 }
 
 /**
 * Handles submitting of the rsvp delete confirmation form
 *
 * @ingroup rsvp_form
-* @param $form_id The id of the form submitted.
-* @param $edit The $edit array.
-* @return path a path to redirect after the form submission.
+* 
 */
 function rsvp_delete_form_submit($form, &$form_state) {
-  switch (rsvp_delete($form_state['value']['rid'])) {
-  case RSVP_DELETED:
-    drupal_set_message(t('RSVP deleted.'));
-    break;
-  case RSVP_ERROR_DELETE_USER_RECORDS:
-    drupal_set_message(t('There was an error removing the RSVP user records'));
-    break;
-  case RSVP_ERROR_DELETE_RSVP:
-    drupal_set_message(t('There was an error removing the RSVP'));
-    break;
+  if ($form_state['values']['confirm']) {
+    switch (rsvp_delete($form_state['values']['rid'])) {
+      case RSVP_DELETED:
+        drupal_set_message(t('RSVP deleted.'));
+        break;
+      case RSVP_ERROR_DELETE_USER_RECORDS:
+        drupal_set_message(t('There was an error removing the RSVP user records'), 'error');
+        break;
+      case RSVP_ERROR_DELETE_RSVP:
+        drupal_set_message(t('There was an error removing the RSVP'), 'error');
+        break;
+    }
+    $form_state['redirect'] = 'node/'. $form_state['values']['nid'] .'/rsvp';
   }
-  return 'node/'. $form_state['value']['nid'] .'/rsvp';
 }
 
 
+
 /**
  * Implementation of hook_mail
  * @ingroup rsvp_mail
  */
 function rsvp_mail($key, &$message, $params) {
-  // TODO: continue porting from here
-  $site_name = variable_get('site_name', 'drupal');
-  $title .= t('RSVP: !subject [!site]', array('!subject' => $subject, '!site' => $site_name));
-  $headers = array_merge(
-    $headers, array(
-      'Content-Type' => 'text/html; charset=UTF-8; format=flowed',
-    )
-  );
+
+  //allow html content
+  //$message['headers'] = array_merge($message['headers'], array('Content-Type' => 'text/html; charset=UTF-8; format=flowed'));
+	
+  switch($key) {
+    case 'invite_mail':
+      $message['subject'] = theme('rsvp_invite_mail_subject', $params['invite'], $params['subject']);
+      //$message['body'] = theme('rsvp_invite_mail', $params['invite'], $params['recipientname']);
+      $message['body'] = drupal_html_to_text(theme('rsvp_invite_mail', $params['invite'], $params['recipientname']));
+      break;
+    case 'message_mail':
+      $message['subject'] = theme('rsvp_message_mail_subject', $params['invite'], $params['subject']);
+      $message['body'] = drupal_html_to_text(theme('rsvp_message_mail', $params['invite'], $params['sender'], $params['body'], $params['recipientname']));
+      break;
+  }
 }
 
 /**
-* Sends an email.
-*
+* Sends an invitation email to one attandee.
+* Is beeing called by _rsvp_send_multiple_invitations
 * @ingroup rsvp_mail
 * @param $invite The invite object to send the mail with.
+* @param $rid The Id of the rsvp object.
 * @return boolean. True if mail is successfully sent.
 */
-function rsvp_send_invitation($invite, $from = NULL) {
+function _rsvp_send_one_invitation($invite, $rid, $from = NULL) {
+  global $language;
+	
   if (is_null($from)) {
     global $user;
-    $from = $user->name .' <'. $user->mail .'>';
+    $from = _rsvp_email_getFromField($user->name, $user->mail);
   }
-  $subject = theme('rsvp_invite_mail_subject', $invite);
+
+  $rsvp = rsvp_load($rid);
+  $u = user_load($rsvp->uid);
+
+  $preferred_language = user_preferred_language($u);
+  
+  
   $to = $invite->email;
-  $body = theme('rsvp_invite_mail', $invite);
-  return rsvp_mail('rsvp_invite_email', $to, $subject, $body, $from);
+
+  $params['invite'] = $invite;
+  $params['subject'] = $rsvp->name;
+  
+  return drupal_mail('rsvp', 'invite_mail', $to, $preferred_language, $params, $from);
 }
 
 /**
-* Emails a message to the attendees of an rsvp instance.
+* Send a message by email to specific attendees of an rsvp instance.
 *
 * @ingroup rsvp_mail
-* @param $edit The send message form post data.
+* @param $rid The rsvp id.
+* @param $audience String The audience for the message (maybe, no, yes, all).
+* @param $subject String The subject you want to send.
+* @param $body String The body you want to send.
+* @param $hash The invitee hashcode. 
 * @return string of formatted recipients, or empty string depending on $confirm.
 */
-function rsvp_send_message($edit) {
+function rsvp_send_message($rid, $audience, $subject, $body, $hash = NULL) {
+
   // check whether the message is sent from a user who's invited
   // yet allowed to message other attendees
-  if (!$edit['hash'] || is_null($edit['hash'])) {
+  if (!$hash || is_null($hash)) {
     global $user;
     $sender = $user->name;
-    $from = $user->name .' <'. $user->mail .'>';
+    $from = _rsvp_email_getFromField($user->name, $user->mail);
   }
   else {
-    $inviter = _rsvp_get_invite($edit['hash']);
+    $inviter = _rsvp_get_invite_by_hash($hash);
     $sender = $inviter->email;
-    $from = $inviter->email;
+    $from = _rsvp_email_getFromField($sender, $inviter->email);
   }
-  $site = variable_get("site_name", "drupal");
-  $subject = $edit['subject'];
 
-  $status['success'] = array();
-  $status['failed'] = array();
+  $status['success_send'] = array();
+  $status['failed_send'] = array();
 
-  $attendees = _rsvp_get_attendees($edit['rid']);
+  $attendees = _rsvp_get_attendees($rid);
   while ($attendee = db_fetch_object($attendees)) {
-    $invite = _rsvp_get_invite($attendee->hash);
-
-    $body = t("Hello!\n\nYou have been sent a message by !sender at !site.\n\nYou can view the invitation from where it originated by following this link: \n!url\n\nHere is the message:\n", array('!sender' => $sender, '!site' => $site, '!url' => url("rsvp/email/$invite->hash", array('absolute' => TRUE)))) . $edit['body'];
-
-    $to = $attendee->email;
-    if (rsvp_mail('rsvp_message_mail', $to, $subject, $body, $from)) {
-      $status['success'][$invite->email] = substr($invite->email, 0, strpos($invite->email, '@'));
-    }
-    else {
-      $status['failed'][$invite->email] = substr($invite->email, 0, strpos($invite->email, '@'));
+    $invite = _rsvp_get_invite_by_hash($attendee->hash);
+    
+    if ($audience == RSVP_ATT_ALL || $invite->response == $audience) {
+      $inviteuser = user_load($invite->uid);
+      $to = $attendee->email;
+
+      $preferred_language = user_preferred_language($inviteuser);
+
+      $params['invite'] = $attendee;
+      $params['subject'] = $subject;
+      $params['body'] = $body;
+      $params['sender'] = $sender;
+    
+  
+      if (drupal_mail('rsvp', 'message_mail', $to, $preferred_language, $params, $from)) {
+        $status['success_send'][$invite->email] = _rsvp_getAttendeeEmail($invite);
+      }
+      else {
+        $status['failed_send'][$invite->email] = _rsvp_getAttendeeEmail($invite);
+      }
     }
   }
 
   return $status;
 }
 
+
+
 /**
  * Returns a list of members of newsletters created with Simplenews module.
  *
- * @param $rid int The RSVP ID.
+ * @param $rsvp The RSVP object.
  * @return string List of members.
  */
-function rsvp_list_simplenews($rid) {
+function rsvp_list_simplenews_form(&$form_state, $rsvp) {
+
+  $form = array();
+	
   if (module_exists('simplenews')) {
-    $rsvp = rsvp_load($rid);
-    $content = t('<h3>You may invite people subscribed to newsletters:</h3>');
+
+    $form['rsvp_list_simplenews'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('You may invite people subscribed to newsletters'),
+    );
+    
     $rows = array();
-    $header = array(t('Newsletter name'), array('data' => t('Operations')));
+    $header = array(t('Newsletter name'), array('data' => t('Operations'), 'width' => '20%'));
+
+    
+    foreach (taxonomy_get_tree(variable_get('simplenews_vid', '')) as $term) {
+      $rows[] = array(
+        $term->name,
+        l(t('Add'), 'rsvp/'. $rsvp->rid .'/attendees/simplenews/'. $term->tid /*, 
+        array('attributes' => array('onclick' => "$.get($(this).attr('href'), function(data){ $('#edit-invite-list').val(data); }); return false;"))*/),
+      );
+    }
+
+    if ($pager = theme('pager', NULL, 10, 0)) {
+      $rows[] = array(array('data' => $pager, 'colspan' => '2'));
+    }
+    
+    if (count($rows) == 0) {
+      $rows[] = array(array('data' => t('There are currently no newsletter series.'), 'colspan' => 2));
+    }
+    
+    $table = theme('table', $header, $rows);
+    $form['rsvp_list_simplenews']['table'] = array('#value' => $table);
+    
+  }
+  
+  return $form;  
+}
+
+/**
+ * Returns a list of system roles.
+ *
+ * @param $rsvp The RSVP object.
+ * @return string a list of system roles.
+ */
+function rsvp_list_roles_form(&$form_state, $rsvp) {
+
+  $form = array();
+
+  $form['rsvp_list_roles'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('You may invite site users'),
+  );
+    
+  $rows = array();
+  $header = array(t('Role'), array('data' => t('Operations'), 'width' => '20%') );
+
+  foreach (user_roles(TRUE) as $rid => $role) {
+    $rows[] = array(
+      $role,
+      l(t('Add'), 'rsvp/'. $rsvp->rid .'/attendees/role/'. $rid, 
+      array('onclick' => "$.get($(this).attr('href'), function(data){ $('#edit-invite-list').val(data); }); return false;")),
+    );
+  }
+  if ($pager = theme('pager', NULL, 10, 0)) {
+    $rows[] = array(array('data' => $pager, 'colspan' => '2'));
+  }
+  
+  if (count($rows) == 0) {
+    $rows[] = array(array('data' => t('There are currently no newsletter series.'), 'colspan' => 2));
+  }
+    
+  $table = theme('table', $header, $rows);
+  $form['rsvp_list_roles']['table'] = array('#value' => $table);
+  
+  return $form;
+}
+
+
+/**
+ * Returns a list of newsletter subscribers.
+ *
+ * @param $rsvp The rsvp object.
+ * @param $nlid int The newsletter ID.
+ * @return string list of subscribers.
+ */
+function rsvp_attendees_simplenews_form(&$form_state, $rsvp, $nlid) {
+
+  $form = array();
+	
+  if (is_numeric($nlid)) {
+    $subs = "";
+    $query = db_query('SELECT DISTINCT s.mail FROM {simplenews_subscriptions} s INNER JOIN simplenews_snid_tid t ON s.snid = t.snid WHERE t.tid = %d ORDER BY mail ASC', $nlid);
+    while ($sub = db_fetch_object($query)) {
+      $subs .= $sub->mail ."\r\n";
+    }
+    _rsvp_add_attendees($rsvp->rid, $subs, false);
+  }
+  
+  drupal_goto('rsvp/'. $rsvp->rid .'/attendees');
+  
+  return $form;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Menu callback: rsvp admin general form for rsvp.
+ *
+ * @see rsvp_admin_settings_general_submit()
+ */
+function rsvp_admin_settings_general(&$form_state) {
+  $form = array();
+  
+  $pick_address = RSVP_EMAIL_SITEADDRESS;
+  $from_address = '';
+  
+  $emailfrom = variable_get('rsvp_from_address', NULL);
+  if (isset($emailfrom)) {
+    foreach ($emailfrom as $pick => $email) {
+  	  $pick_address = $pick;
+  	  $from_address = $email; 
+    }
+  }
+  
+  
+  $form['rsvp_admin_settings_general'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Sender information'),
+    '#collapsible' => FALSE,
+    '#description' => t('Default sender address that will be used for rsvp-invite and rsvp-message emails.'),
+  );
+
+  $form['rsvp_admin_settings_general']['pick_from_address'] =  array(
+    '#type' => 'select',
+    '#title' => t('Pick which email address to use for emails'),
+    '#default_value' => $pick_address,
+    '#options' => array(RSVP_EMAIL_SITEADDRESS => t('The sites default address (ignore email address below)'), RSVP_EMAIL_SETTINGS => t('Use the email adress below'), RSVP_EMAIL_CREATOR =>  t('Use the RSVPs creator email (ignore email address below)')),
+  );
+  
+  $form['rsvp_admin_settings_general']['rsvp_from_address'] = array(
+    '#type' => 'textfield',
+    '#title' => t('From email address'),
+    '#size' => 60,
+    '#maxlength' => 128,
+    '#required' => false,
+    '#default_value' => $from_address,
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save'),
+    '#weight' => 25,
+  );
+  
+  return $form;
+}
+
+function rsvp_admin_settings_general_validate($form, &$form_state) {
+
+  if ($form_state['values']['pick_from_address'] == '1') {
+    if (!valid_email_address($form_state['values']['rsvp_from_address'])) {
+      form_set_error('rsvp_from_address', t("The sender's email address you supplied is not valid."));
+    }
+  }
+}
+  
+function rsvp_admin_settings_general_submit($form, &$form_state) {
+
+  $pick = $form_state['values']['pick_from_address'];
+  $email = $form_state['values']['rsvp_from_address'];
+
+  //always store emailaddress, even if not used
+  variable_set('rsvp_from_address', array($pick => $email));
+
+  drupal_set_message('Settings have been stored.');
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Menu callback: rsvp admin current associations form for rsvp.
+ *
+ */
+function rsvp_admin_settings_types(&$form_state) {
+
+  $form = array();
+
+  
+  $connector = new RsvpConnector();
+  if (!$connector->isTypesAreSelectable()) {
+    return $form;   
+  }
+  
+  // The table with all associations
+  
+  $header = array(t('Content type'), t('Field'), t('Description'), t('Operation'));
+  
+  $rsvp_content_types = variable_get('rsvp_content_types', array());
+
+  $rows = array();
+  foreach ( $rsvp_content_types as $contenttype => $field ) {
+    $ct = content_types($contenttype);
+    
+    $rows[] = array(l($ct['name'], 'admin/content/node-type/'. $contenttype),
+                    t($field),
+                    t($ct['description']),
+                    l(t('delete'), 'admin/settings/rsvp/types/delete/'. $contenttype, array(), drupal_get_destination())
+                    );
+  }
+  
+  
+  if ($pager = theme('pager', NULL, 10, 0)) {
+    $rows[] = array(array('data' => $pager, 'colspan' => '3'));
+  }
+  if (!$rows) {
+    $rows[] = array(array('data' => t('No associations available.'), 'colspan' => '3'));
+  }
+
+  $table = theme('table', $header, $rows);
+
+  $form['table'] = array('#value' => $table);
+  
+  
+  return $form;
+      
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Menu callback: rsvp admin add new association for rsvp.
+ *
+ */
+function rsvp_admin_settings_types_add(&$form_state) {
+    
+  $form = array();
+
+  $connector = new RsvpConnector();
+  if (!$connector->isTypesAreSelectable()) {
+    return $form;   
+  }
+  
+  // The table with all Content Types
+  
+  $header = array(t('Content type'), t('Description'), t('Operation'));
+
+  $rsvp_content_types = variable_get('rsvp_content_types', array());
+  $contenttypes = node_get_types('types');
+
+  //remove all types from $contenttypes that we already selected
+  foreach ( $rsvp_content_types as $contenttype => $field ) {
+    unset($contenttypes[$contenttype]);
+  }
+  
+  //var_dump($contenttypes);
+  
+  $rows = array();
+  foreach ($contenttypes as $ct) {
+    $rows[] = array(l($ct->name, 'admin/content/node-type/'. $ct->type),
+                    t($ct->description),
+                    l(t('add'), 'admin/settings/rsvp/types/add/'. $ct->type, array(), drupal_get_destination())
+                    );
+  }
+  
+  
+  if ($pager = theme('pager', NULL, 10, 0)) {
+    $rows[] = array(array('data' => $pager, 'colspan' => '3'));
+  }
+  if (!$rows) {
+    $rows[] = array(array('data' => t('No associations available.'), 'colspan' => '3'));
+  }
+
+  $table = theme('table', $header, $rows);
+
+  $form['table'] = array('#value' => $table);
+  
+  
+  return $form;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Menu callback: Delete association entry.
+ *
+ * @see rsvp_admin_settings_types_delete_submit()
+ */
+
+function rsvp_admin_settings_types_delete(&$form_state, $contenttype = NULL) {
+
+  if (!isset($contenttype)) {
+    drupal_not_found();
+    return;
+  }
+  
+  $form = array();
+  
+  $connector = new RsvpConnector();
+  if (!$connector->isTypesAreSelectable()) {
+    drupal_goto($return_url);
+  }
+    
+  $form['contenttype'] = array( '#type' => 'value', '#value' => $contenttype);
+  
+  $ct = content_types($contenttype);
+  
+  $form['notice'] = array(
+    '#value' => '<p><strong>'. t('Note: All RSVP using this content type will be lost.') .'</strong></p>',
+  );
+
+  return confirm_form($form,
+    t('Are you sure you want to delete the RSVP association with %type?', array('%type' => $ct['name'])),
+    'admin/settings/rsvp/types',
+    t('This action cannot be undone.'),
+    t('Delete'),
+    t('Cancel')
+  );
+}
 
-    foreach (taxonomy_get_tree(_simplenews_get_vid()) as $term) {
-      $rows[] = array(
-        $term->name,
-        l(t('Add'), 'node/'. $rsvp->nid .'/rsvp/'. $rsvp->rid .'/attendees/simplenews/'. $term->tid, 
-        array('onclick' => "$.get($(this).attr('href'), function(data){ $('#edit-invite-list').val(data); }); return false;")),
-      );
-    }
+function rsvp_admin_settings_types_delete_submit($form, &$form_state) {
+  if ($form_state['values']['confirm']) {
+
+//    TODO: remove RSVPs related to this field from the db 
+  	
+  	$contenttype = $form_state['values']['contenttype'];
+
+    $ct = content_types($contenttype);
+    
+    $rsvp_content_types = variable_get('rsvp_content_types', array());
+    unset($rsvp_content_types[$contenttype]);
+    variable_set('rsvp_content_types', $rsvp_content_types);  
+
+    drupal_set_message(t('Association with content type %type and field %field has been removed.', array('%type' => $ct['name'], '%field' => $field)));
 
-    if (count($rows) == 0) {
-      $rows[] = array(array('data' => t('There are currently no newsletter series.'), 'colspan' => 2));
-    }
-    $content .= theme('table', $header, $rows);
-    return $content;
   }
+  
+  $form_state['redirect'] = 'admin/settings/rsvp/types';
+  
 }
 
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
 /**
- * Returns a list of system roles.
+ * Menu callback: rsvp admin add new association form for rsvp.
  *
- * @param $rid int The RSVP ID.
- * @return string a list of system roles.
+ * @see rsvp_admin_settings_types_add_field_submit()
  */
-function rsvp_list_roles($rid) {
-  $rsvp = rsvp_load($rid);
-  $content = t('<h3>You may invite site users:</h3>');
-  $rows = array();
-  $header = array(t('Role'), array('data' => t('Operations')));
+function rsvp_admin_settings_types_add_field(&$form_state, $contenttype = NULL) {
 
-  foreach (user_roles(TRUE) as $rid => $role) {
-    $rows[] = array(
-      $role,
-      l(t('Add'), 'node/'. $rsvp->nid .'/rsvp/'. $rsvp->rid .'/attendees/role/'. $rid, 
-      array('onclick' => "$.get($(this).attr('href'), function(data){ $('#edit-invite-list').val(data); }); return false;")),
-    );
+  if (!isset($contenttype)) {
+    drupal_not_found();
+    return;
   }
+  
+  $form = array();
+  $fields = array();
+  
+  $connector = new RsvpConnector();
+
+  if (!$connector->hasMultipleFields()) {
+    //return e.g. for event connector here because we have exactly one field, and the connector knows its name
+    $rsvp_content_types = variable_get('rsvp_content_types', array());
+    $rsvp_content_types[$contenttype] = '';      
+    variable_set('rsvp_content_types', $rsvp_content_types);  
+    drupal_set_message(t('Association for content type %type has been added.', array(type => '$contenttype')));
+    drupal_goto('admin/settings/rsvp/types');
+    return $form;
+  }  
+  
+  // collect cck fields
+  $ct = content_types($contenttype);
+  
+  // Loop the fields for the given type
+  foreach ( $ct['fields'] as $field_name => $field ) {
+    $fields[$field_name] = $field['field_name'];
+  }  
+
+  $form['rsvp_admin_settings_types_add_field']['event_contenttype'] = array(
+    '#type' => 'item',
+    '#title' => t('For content type'),
+    '#value' => t($ct['name']),
+  );
+  
+  
+  $form['rsvp_admin_settings_types_add_field']['event_start_field'] = array(
+    '#type' => 'select',
+    '#title' => t('Event start field'),
+    '#required' => TRUE,
+    '#options' => array_map('check_plain', $fields),
+//    '#default_value' => isset($vocabulary) ? $vocabulary->nodes : array(),
+    '#description' => t('%contenttype field to be used as rsvp start date.', array('%contenttype' => $contenttype)),
+  );
 
-  $content .= theme('table', $header, $rows);
-  return $content;
+  $form['rsvp_admin_settings_types_add_field']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save'),
+    '#weight' => 25,
+  );
+  
+  $form['contenttype'] = array('#type' => 'value', '#value' => $contenttype);
+  
+  return $form;
 }
 
-/**
- * Returns a list of newsletter subscribers.
- *
- * @param $nlid int The newsletter ID.
- * @return string list of subscribers.
- */
-function rsvp_attendees_simplenews($nlid) {
-  $subs = "";
-  $query = db_query('SELECT DISTINCT s.mail FROM {simplenews_subscriptions} s INNER JOIN simplenews_snid_tid t ON s.snid = t.snid WHERE t.tid = %d ORDER BY mail ASC', $nlid);
-  while ($sub = db_fetch_object($query)) {
-    $subs .= $sub->mail ."\r\n";
-  }
-  print $subs;
-  exit();
+function rsvp_admin_settings_types_add_field_submit($form, &$form_state) {
+
+  $contenttype = $form_state['values']['contenttype'];
+  $field = $form_state['values']['event_start_field'];
+
+  $ct = content_types($contenttype);
+    
+  $rsvp_content_types = variable_get('rsvp_content_types', array());
+  $rsvp_content_types[$contenttype] = $field;     
+  variable_set('rsvp_content_types', $rsvp_content_types);  
+    
+  drupal_set_message(t('Association with content type %type and field %field has been added.', array('%type' => $ct['name'], '%field' => $field)));
+
+  // Return to Association list page after submit
+  $form_state['redirect'] = 'admin/settings/rsvp/types';  
 }
 
+    
+
+
 /**
  * Returns a list of users in a specific role.
  *
- * @param $rid int The role ID.
+ * @param $rsvp The rsvp object.
+ * @param $roleid int The role ID.
  * @return string list of users.
  */
-function rsvp_attendees_users($rid) {
-  if (is_numeric($rid)) {
+function rsvp_attendees_users_form(&$form_state, $rsvp, $roleid) {
+
+  $form	= array();
+
+  if (is_numeric($roleid)) {
     $subs = "";
     // if the requested role is authenticated, no records will be returned from
     // normal query
-    if ($rid == 2) {
+    if ($roleid == 2) {
       $query = db_query('SELECT name FROM {users} ORDER BY uid DESC');
     }
     else {
-      $query = db_query('SELECT name FROM {users} u INNER JOIN {users_roles} ur ON u.uid = ur.uid WHERE ur.rid = %d ORDER BY u.uid DESC', $rid);
+      $query = db_query('SELECT name FROM {users} u INNER JOIN {users_roles} ur ON u.uid = ur.uid WHERE ur.rid = %d ORDER BY u.uid DESC', $roleid);
     }
     while ($u = db_fetch_object($query)) {
       $subs .= $u->name ."\r\n";
     }
-    print $subs;
-    exit();
+
+    _rsvp_add_attendees($rsvp->rid, $subs, false);
   }
+  
+  drupal_goto('rsvp/'. $rsvp->rid .'/attendees');
+  
+  return $form;
 }
 
+
+
 /**
 * Returns the rsvps that a user is the owner of.
 *
 * @ingroup rsvp_functions
-* @param $uid The uid of the user.
+* @param $nid The nid of the node.Can be one, array or NULL which means all nodes of the user.
+* @param $uid The uid of the user.Can be a user or NULL which means rsvp for all users.
 * @return dbresultset of rsvps.
 */
 function _rsvp_get_rsvps($nid = NULL, $uid = NULL, $tablesort = ' ORDER BY nid') {
-  if (!$uid) {
-    global $user;
-    $uid = $user->uid;
+
+  global $user;
+  $session_uid = $user->uid;
+  $query = 'SELECT r.*, n.title FROM {rsvp} r INNER JOIN {node} n ON r.nid = n.nid '; //r.uid = %d';
+	
+  if (!is_null($uid) || !is_null($nid)) {
+    $query .= 'WHERE ';	
   }
-  $query = 'SELECT r.*, n.title FROM {rsvp} r INNER JOIN {node} n ON r.nid = n.nid WHERE r.uid = %d';
+  
+  //$query = 'SELECT r.*, n.title FROM {rsvp} r INNER JOIN {node} n ON r.nid = n.nid WHERE r.uid = %d';
   if (!is_null($nid)) {
     if (is_array($nid)) {
-      $query .= ' AND r.nid IN (%s)';
+      $query .= 'r.nid IN (%s) ';
       $nid = implode(', ', $nid);
     }
     elseif (is_numeric($nid)) {
-      $query .= ' AND r.nid = %d';
+      $query .= 'r.nid = %d ';
     }
   }
+  
+  if (!is_null($uid)) {
+  	  if (!is_null($nid)) {
+        $query .= 'AND ';
+  	  }
+    $query .= 'r.uid = %d';
+  }
+  
+  
   $query .= $tablesort;
-  return db_query($query, $uid, $nid);
+  
+  if (is_null($nid)) {
+    return db_query($query, $uid); 	
+  }
+  else {
+    return db_query($query, $nid, $uid);
+  }
+  
 }
 
 /**
@@ -1397,30 +2661,56 @@
 }
 
 /**
+* Returns a particular invite that a user has received.
+*
+* @ingroup rsvp_functions
+* @param $rid The rsvp id of the invitation.
+* @param $uid The uid of the user.
+* 
+* @return array of event nids.
+*/
+function _rsvp_get_invite_by_rid($rid, $uid = NULL) {
+  if (!$uid) {
+    global $user;
+    $uid = $user->uid;
+  }
+
+  return db_fetch_object(db_query('SELECT * FROM {rsvp_invite} u WHERE u.uid = %d AND u.rid = %d', $uid, $rid));
+}
+
+
+/**
 * Returns an invite by hash value.
 *
 * @ingroup rsvp_functions
 * @param $hash The hash value of the invite.
 * @return dbresultset of the requested invite.
 */
-function _rsvp_get_invite($hash) {
+function _rsvp_get_invite_by_hash($hash) {
   return db_fetch_object(db_query('SELECT * FROM {rsvp} r LEFT JOIN {rsvp_invite} u ON r.rid = u.rid WHERE u.hash = \'%s\'', $hash));
 }
 
 /**
-* Returns the invites that a user has received for a specific event node.
+* Returns the rsvps that a user has received for a specific event node.
 *
 * @ingroup rsvp_functions
 * @param $nid The nid of the node.
-* @param $uid The uid of the user.
+* @param $uid The uid of the user. If null, return all from all users.
 * @return array of event nids.
 */
 function _rsvp_get_node_invites($nid, $uid = NULL) {
-  if (!$uid) {
-    global $user;
-    $uid = $user->uid;
+
+//  if (!$uid) {
+//    global $user;
+//    $uid = $user->uid;
+//  }
+  
+  $query = 'SELECT * FROM {rsvp} r LEFT JOIN {rsvp_invite} u ON r.rid = u.rid WHERE r.nid = %d';
+  if (!is_null($uid)) {
+    $query .= ' AND u.uid = %d';
   }
-  return db_query('SELECT * FROM {rsvp} r LEFT JOIN {rsvp_invite} u ON r.rid = u.rid WHERE u.uid = %d AND r.nid = %d', $uid, $nid);
+  
+  return db_query($query, $nid, $uid);
 }
 
 /**
@@ -1430,8 +2720,8 @@
 * @param $rid The rid of the rsvp instance.
 * @return dbresultset of the requested attendees.
 */
-function _rsvp_get_attendees($rid, $status = 'all', $count = FALSE) {
-  if ($status == 'all' || !isset($status))
+function _rsvp_get_attendees($rid, $status = RSVP_ATT_ALL, $count = FALSE) {
+  if ($status == RSVP_ATT_ALL || !isset($status))
     return db_query('SELECT '. ($count ? 'COUNT(*)' : '*') .' FROM {rsvp_invite} WHERE rid = %d', $rid);
   else
     return db_query('SELECT '. ($count ? 'COUNT(*)' : '*') .' FROM {rsvp_invite} WHERE rid = %d AND response=\'%s\'', $rid, $status);
@@ -1465,22 +2755,18 @@
 }
 
 /**
-* Checks if an email address already exists for an rsvp.
+* Checks if an email address already exists for an rsvp and returns it.
 *
 * @ingroup rsvp_functions
 * @param $rid The id of the rsvp.
 * @param $email The email to check for.
-* @return boolean true if the email exists for the rsvp.
+* @return boolean false if the email not exists for the rsvp, or the $invitation object.
 */
 function _rsvp_attendee_exists($rid, $email) {
-  if (db_result(db_query('SELECT COUNT(*) FROM {rsvp_invite} WHERE rid = %d AND email = \'%s\'', $rid, $email)) > 0) {
-    return TRUE;
-  }
-  else {
-    return FALSE;
-  }
+  return db_fetch_object(db_query('SELECT * FROM {rsvp_invite} WHERE rid = %d AND email = \'%s\'', $rid, $email));
 }
 
+
 /**
 * Checks to see if a user has been invited to an event.
 *
@@ -1508,16 +2794,32 @@
 }
 
 /**
-* Checks to see if an rsvp is blind has been invited to an event.
+* Checks to see if responses are visible to other attendees.
+*
+* @ingroup rsvp_functions
+* @param $rid The rid of the rsvp.
+* @return Int. 0:Show responses, 1:Hide responses, 2:Hide responses until replied 
+* 
+*/
+
+function _rsvp_is_response_blind($rid) {
+  $status = db_fetch_object(db_query('SELECT response_blind FROM {rsvp} WHERE rid = %d', $rid));
+
+  return $status->response_blind;
+}
+
+/**
+* Checks to see if attendees are visible to other attendees.
 *
 * @ingroup rsvp_functions
 * @param $rid The rid of the rsvp.
-* @return boolean. False if the rsvp is blind.
+* @return Int. 0:Show attendees, 1:Hide attendees always, 2:Hide attendees until replied 
 */
-function _rsvp_is_blind($rid) {
-  $status = db_fetch_object(db_query('SELECT blind FROM {rsvp} WHERE rid = %d', $rid));
 
-  return $status->blind;
+function _rsvp_is_attendees_visible($rid) {
+  $status = db_fetch_object(db_query('SELECT attendees_visible FROM {rsvp} WHERE rid = %d', $rid));
+
+  return $status->attendees_visible;
 }
 
 /**
@@ -1590,30 +2892,26 @@
  */
 
 /**
-* Emails the invite to the attendees of an rsvp instance.
+* Emails the invitation to all attendees of an rsvp instance.
 *
 * @ingroup rsvp_mail
 * @param $rid The rid of the rsvp.
 * @param $resend True: sends only to recipients with received flag not set. default: false.
 * @return array of status values.
 */
-function _rsvp_mail_rsvp($rid, $from = NULL, $resend = FALSE) {
-  $status['success'] = array();
-  $status['failed'] = array();
+function _rsvp_send_multiple_invitations($rid, $from = NULL, $resend = FALSE) {
+  $status['success_send'] = array();
+  $status['failed_send'] = array();
   $attendees = _rsvp_get_attendees($rid);
   while ($attendee = db_fetch_object($attendees)) {
     if (!($resend && $attendee->received) && !($attendee->invited)) {
-      $invite = _rsvp_get_invite($attendee->hash);
-      if (rsvp_send_invitation($invite, $from)) {
+      $invite = _rsvp_get_invite_by_hash($attendee->hash);
+      if (_rsvp_send_one_invitation($invite, $rid, $from)) { 
         db_query('UPDATE {rsvp_invite} SET invited = 1 WHERE hash = \'%s\'', $attendee->hash);
-        // hide e-mails for system users
-        $user = user_load(array('uid' => $attendee->uid));
-        $status['success'][] = ($user->uid == 0 ? $invite->email : $user->name);
+        $status['success_send'][] = _rsvp_getAttendeeEmail($invite);
       }
       else {
-        // hide e-mails for system users
-        $user = user_load(array('uid' => $attendee->uid));
-        $status['failed'][] = ($user->uid == 0 ? $invite->email : $user->name);
+        $status['failed_send'][] = _rsvp_getAttendeeEmail($invite);
       }
     }
   }
@@ -1629,3 +2927,398 @@
 function _rsvp_html_head() {
   drupal_add_css(drupal_get_path('module', 'rsvp') .'/rsvp.css');
 }
+
+
+/*
+ * Access function to determine if the logged-in user is allowed to work with RSVP's in the context of a certain node.
+
+ * We also check here if the node type is entitled to have an rsvp connected
+ *
+ * @param $node The node object you want to check.
+ * @return true or false.
+ */
+function rsvp_user_node_access($connector, $node, $rid = 0, $addtlparam = NULL) {
+
+  global $user;
+
+  if (!is_numeric($rid))
+    return false;
+    
+  if (!$connector->is_event_enabled($node->type))
+    return false;
+    
+  if (!is_null($addtlparam)) {  
+    $addtlaccess = user_access($addtlparam);
+  }
+  else {
+    $addtlaccess = true;
+  }
+      
+    return ((user_access('administer rsvp') || 
+            user_access('maintain rsvp') || 
+            user_access('rsvp on events') || 
+            ($node->uid == $user->uid && user_access('rsvp on own events'))
+         ) && $addtlaccess );
+  }
+
+/*
+ * Access function to determine if the logged-in user is allowed to work with a particular RSVP.
+ *
+ * @param $rsvp The rsvp object you want to check.
+ * @param $addtlparam String, check for an additional permission.
+ *  * @return true or false.
+ */
+function rsvp_user_rsvp_access($connector, $rsvp, $addtlparam = NULL) {
+
+
+  if (is_null($rsvp))
+    return false;
+
+  $node = node_load($rsvp->nid);
+  
+  if (!isset($node))
+    return false;
+
+  return rsvp_user_node_access($connector, $node, $rsvp->rid, $addtlparam);
+}
+
+/*
+ * Access function for the admin/settings section to determine if the logged-in user 
+ * 1) has admin permissions and 
+ * 2) the current connector supports content-type associations or not
+ * 
+ * @param $connector The connector you are using.
+ * @return true or false.
+ *  
+ */
+function rsvp_admin_type_access($connector) {
+
+  if (!$connector->isTypesAreSelectable())
+    return false;
+      
+    return (user_access('administer rsvp'));
+}
+
+/*
+ * Access function to determine if the logged-in user is allowed to export attendees to CSV
+ * 
+ * @param $rsvp The Rsvp you want to check.
+ * @return true or false.
+ *  
+ */
+function rsvp_user_attendees_cvs_access($rsvp) {
+
+  return rsvp_visible_responses_access($rsvp->rid);
+		
+}
+
+/*
+ * general access function to determine if the logged-in user is allowed to invite more users
+ * 
+ * @param $invite The invitation object you want to check.
+ * @return true or false.
+ */
+function rsvp_user_attendees_viral_access($invite) {
+
+  if (!_rsvp_is_invite_viral($invite->rid))
+    return false;
+      
+  return (user_access('access content'));
+}
+
+/*
+ * Access function to determine if the logged-in user is allowed to see the attendee page
+ * 
+ * @param $invite The invitation object you want to check.
+ * @return true or false.
+ *  
+ * returns true if an invitee is allowed to invite more users
+ * or if the user is allowed to see results about other attendees.
+ * Useful to determine if the "Attendee" tab has to be enabled or not.
+ */
+function rsvp_user_attendees_view_access($connector, $invite) {
+
+  return (_rsvp_is_invite_viral($invite->rid)
+            || rsvp_visible_responses_access($invite->rid));
+}
+
+
+/*
+ * Access function to determine if the logged-in user is allowed to send emails to other user.
+ * 
+ * @param $invite The invitation object you want to check.
+ * @return true or false.
+ */
+function rsvp_message_hash_access($connector, $invite) {
+
+  $rsvp = rsvp_load($invite->rid);
+	
+  if (rsvp_user_rsvp_access($connector, $rsvp))
+    return true;
+	
+  if (!_rsvp_is_invite_message_enabled($invite->rid))
+    return false;
+      
+  return (user_access('access content'));
+}
+
+
+/*
+ * Access function to determine if the logged-in user is allowed to see the attendees by name or not.
+ * 
+ * @param $rid Int The Rsvp Id you want to check
+ * @return true or false.
+ *  
+ */
+function rsvp_visible_attendees_access($rid) {
+
+  $attendees_visible = _rsvp_is_attendees_visible($rid);
+  $owner = _rsvp_is_owner($rid);
+
+  if ($owner || user_access('administer rsvp') || user_access('maintain rsvp')) {
+    return true;
+  }
+      
+  if ($attendees_visible == 1)
+    return false;
+    
+  return (user_access('access content'));
+}
+
+/*
+ * Access function to determine if the logged-in user is allowed to see responses to a rsvp or not.
+ * 
+ * @param $rid Int The Rsvp Id you want to check
+ * @return true or false.
+ *  
+ */
+function rsvp_visible_responses_access($rid) {
+
+  $rsvp = rsvp_load($rid);
+
+  if (!isset($rsvp))
+    return false;
+  
+  $response_blind = $rsvp->response_blind;
+  $owner = _rsvp_is_owner($rid);
+
+  if ($owner || user_access('administer rsvp') || user_access('maintain rsvp')) {
+    return true;
+  }
+    
+  if ($response_blind == RSVP_RESPONSE_HIDE)
+    return false;
+    
+  if ($response_blind == RSVP_RESPONSE_SHOWWHENREPLIED) {
+  	//find invitation and check if user has already answered?
+    $invitation = _rsvp_get_invite_by_rid($rid);
+    if (!isset($invitation) || ($invitation->response == 'none')) {
+      return false;
+    }
+  }
+    
+  return (user_access('access content'));
+}
+
+
+
+/**
+ * Returns the field associated with a content type.
+ *
+ * @ingroup rsvp_functions
+ * @return a field as string
+ */
+function _rsvp_getField($contenttype) {
+
+  $rsvp_content_types = variable_get('rsvp_content_types', array());
+  return $rsvp_content_types[$contenttype];
+}   
+
+
+/**
+ * Certain users are not allowed to see the attendent email. In that case return the username instead.
+ * also allows to hide e-mails for system users in general
+ *
+ * @param $attendee The invitation object.
+ * @param $stripEmailAddress Boolean show onlypart of the emailaddress.
+ * @return email 
+ */
+function _rsvp_getAttendeeEmail($attendee, $stripEmailAddress = true) {
+
+  if ($attendee->uid) {
+    $u = db_fetch_object(db_query("SELECT uid, name FROM {users} WHERE uid = %d", $attendee->uid));
+    return $u->name;
+  }
+  else {
+    return (!$stripEmailAddress ? $attendee->email : substr($attendee->email, 0, strpos($attendee->email, '@')));
+  }
+}
+
+/**
+ * Depending on the rsvp setting, the From address is being picked.
+ * @param $username The user name that initiates the email.
+ * @param $useremail The user email that initiates the email.
+ * @return emailaddress as String. 
+ */
+function _rsvp_email_getFromField($username, $useremail) {
+
+  $pick_address = RSVP_EMAIL_SITEADDRESS;
+  $from_target = $from_creator = $username .' <'. $useremail .'>';
+  	
+  $emailfrom = variable_get('rsvp_from_address', NULL);
+  if (isset($emailfrom)) {
+    foreach ($emailfrom as $pick => $email) {
+      $pick_address = $pick;
+      $from_address = $email; 
+    }
+  }
+
+  switch($pick_address) {
+  	case RSVP_EMAIL_SITEADDRESS: //The sites default address
+  	  $from_target =  variable_get('site_mail', ini_get('sendmail_from'));
+      break;
+  	  case RSVP_EMAIL_SETTINGS: //Use the email adress selected in the options menue
+      $from_target = from_address;
+      break;
+    default:
+    case RSVP_EMAIL_CREATOR: //Use the RSVPs creator email
+      $from_target =  $from_creator;
+      break;
+      
+  }
+  return $from_target;	
+}
+
+
+    
+///////////////////////////////////////////////////////////////////////////
+
+/* The class EventConnector which delegates the call to the appropriate eventconnector implementation
+*/
+
+class RsvpConnectorImpl {
+
+  //returns a unix date (int) as String. (and already converted to the correct timezone).
+//  function print_unixDateAsString($unixdate) { 
+//  	return NULL;
+//  } 
+	
+  function get_datecount($node, $field) {
+    return NULL;
+  }
+	
+  //returns startdate as unix timestamp in utc
+  function get_startdate($node, $field, $pos) {
+    return NULL;
+  }
+  
+  //returns startdate as string in local timezone.
+  function get_startdateAsString($node, $field, $pos) {
+    return NULL;
+  }
+  
+  //returns enddate as unix timestamp in utc
+  function get_enddate($node, $field, $pos) {
+    return NULL;
+  }
+
+  //returns the position for a particular hash, or -1 if invalid hash
+  function get_posByHash($node, $field, $hash) {
+    return NULL;
+  }
+
+  function is_event_enabled($contenttype) {
+    return NULL;
+  }
+
+  function isTypesAreSelectable() {
+    return NULL;
+  }
+
+  //returns true if the connector supports multiple fields per content-type. (e.g. Repeatable dates in Date API).
+  function hasMultipleFields() {
+    return NULL;
+  }
+  
+}
+
+class RsvpConnector {
+  var $connector;
+
+  function RsvpConnector() {
+
+  	$connectorstring = variable_get('rsvp_connector', NULL);
+
+  	if (isset($connectorstring))
+  	{
+      $funcname = 'rsvp_' . $connectorstring . 'connector_getconnector'; 	
+  	
+  	  if (function_exists($funcname))
+  	  {
+  	  	$this->connector = call_user_func  ( $funcname );
+  	  }
+  	}
+  	else {
+  	  //do noything here. A clean system without enabled connector does not know about the variable yet.	
+  	  //die('No RSVP connector has been enabled.');
+  	}
+  }
+  
+  //returns a unix date (int) as String. (and already converted to the correct timezone).
+//  function print_unixDateAsString($unixdate) {  
+//    return $this->connector->print_unixDateAsString($unixdate);
+//  } 
+  
+  function get_datecount($node, $field) {
+    return $this->connector->get_datecount($node, $field);
+  }
+  
+  //returns startdate as unix timestamp in utc
+  function get_startdate($node, $field, $pos) {
+  	return $this->connector->get_startdate($node, $field, $pos);
+  }
+  
+  //returns startdate as string in local timezone
+  function get_startdateAsString($node, $field, $pos) {
+    return $this->connector->get_startdateAsString($node, $field, $pos);
+  }
+  
+  //returns enddate as unix timestamp in utc
+  function get_enddate($node, $field, $pos) {
+    return $this->connector->get_enddate($node, $field, $pos);
+  }
+  
+  //returns the position for a particular hash, or -1 if invalid hash
+    function get_posByHash($node, $field, $hash) {
+    return $this->connector->get_posByHash($node, $field, $hash);
+  }
+  
+  function is_event_enabled($contenttype) {
+    return $this->connector->is_event_enabled($contenttype);
+  }
+
+
+  //returns true if the connector supports events on various content-types that need to be selected in the admin section.
+  function isTypesAreSelectable() {
+    // this is necessary for initial menu rebuild when connectors are not enabled yet.    
+  	if (isset($this->connector))
+  	  return $this->connector->isTypesAreSelectable();
+  	else
+  	  return false;
+  }
+
+  //returns true if the connector supports multiple fields per content-type. (e.g. Repeatable dates in Date API).
+  function hasMultipleFields() {
+    return $this->connector->hasMultipleFields();
+  }
+  
+}
+
+function rsvpGetSessionVar($key, $default) {
+  $value = isset($_SESSION[$key]) ? $_SESSION[$key] : $default;
+  return $value;
+}    
+
+function rsvpSetSessionVar($key, $value) {
+  $_SESSION[$key] = $value;
+}    
Index: rsvp.theme
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rsvp/rsvp.theme,v
retrieving revision 1.5
diff -u -r1.5 rsvp.theme
--- rsvp.theme	31 Aug 2007 23:40:36 -0000	1.5
+++ rsvp.theme	16 Nov 2008 04:57:01 -0000
@@ -4,83 +4,115 @@
  * @{
  */
 
-function theme_rsvp_send_status($status) {
+function theme_rsvp_send_status($status = NULL) {
+  if(count($status) == 0) {
+    $content .= '<div class="title">'. t('No recipients found.') .'</div>';
+  }
   if(count($status['invalid'])) {
     $content .= '<div class="title">'. t('The following recipient(s) are invalid:') .'</div>';
     $content .= theme('item_list', $status['invalid']);
   }
   if(count($status['existing'])) {
-    $content .= '<div class="title">'. t('The following recipient(s) already exist:') .'</div>';
+    $content .= '<div class="title">'. t('The following recipient(s) could not be added, because they already have been added earlier:') .'</div>';
     $content .= theme('item_list', $status['existing']);
   }
-  if(count($status['failed'])) {
+  if(count($status['failed_add'])) {
+    $content .= '<div class="title">'. t('Failed adding these recipient(s):') .'</div>';
+    $content .= theme('item_list', $status['failed_add']);
+  }
+  if(count($status['failed_send'])) {
     $content .= '<div class="title">'. t('Failed sending email to these recipient(s):') .'</div>';
-    $content .= theme('item_list', $status['failed']);
+    $content .= theme('item_list', $status['failed_send']);
+  }
+  if(count($status['success_add'])) {
+    $content .= '<div class="title">'. t('Successfully added these recipient(s):') .'</div>';
+    $content .= theme('item_list', $status['success_add']);
   }
-  if(count($status['success'])) {
+  if(count($status['success_send'])) {
     $content .= '<div class="title">'. t('Successfully sent email to these recipient(s):') .'</div>';
-    $content .= theme('item_list', $status['success']);
+    $content .= theme('item_list', $status['success_send']);
   }
   return '<div class="rsvpmailstatus">'. $content .'</div>';
 }
 
-function theme_rsvp_event($node) {
-  $content .= '<div>For: '. l($node->title, 'node/'. $node->nid);
-  $content .= ' - '. format_date($node->event_start, 'small', '', $node->start_offset) .'</div>';;
+function theme_rsvp_event($node = NULL, $startdate = NULL) {
+  $content .= '<div>For: '. l(check_plain($node->title), 'node/'. $node->nid);
+  $content .= ' - '. check_plain($startdate) .'</div><br />';
+  return $content;
+}
+
+function theme_rsvp_event_anonymous() {
+  $content = '<div>Please sign-in to display details about other attendees.</div><br />';
   return $content;
 }
 
-function theme_rsvp_invite($invite, $rsvp, $content) {
+function theme_rsvp_invite($invite = NULL, $rsvp = NULL, $content = NULL) {
   $output = '<div class="rsvpbox">';
-  $output .= $content;
+  $output .= check_markup($content);
   $output .= '</div>';
   return $output;
 }
 
-function theme_rsvp_preview($content) {
+function theme_rsvp_preview($content = NULL) {
   $output = '<div class="rsvppreviewbox">';
   $output .= '<div class="title">Invite Preview</div>';
-  $output .= '<div class="rsvpbox">'. $content .'</div>';
+  $output .= '<div class="rsvpbox">'. check_markup($content) .'</div>';
   $output .= '</div>';
   return $output;
 }
 
-function theme_rsvp($rsvp, $content) {
+function theme_rsvp($rsvp = NULL, $content = NULL) {
   $u = user_load(array('uid' => $rsvp->uid));
-  $title = t('!name has invited you to %title', array('!name' => l($u->name, 'user/'. $u->uid), '%title' => $rsvp->name));
+  $title = t('!name has invited you to %title', array('!name' => l(check_plain($u->name), 'user/'. $u->uid), '%title' => $rsvp->name));
   $output .= theme('box', $title, $content);
   return $output;
 }
 
-function theme_rsvp_reply($content) {
+function theme_rsvp_reply($content = NULL) {
   $output = '<div class="rsvpreplybox">';
-  $output .= $content;
+  $output .= check_markup($content) . 'NOT USED ANYMORE';
   $output .= '</div>';
   return $output;
 }
 
-function theme_rsvp_invite_action($content) {
+function theme_rsvp_invite_action($content = NULL) {
   $output = '<div class="rsvpactionbox">';
-  $output .= $content;
+  $output .= check_markup($content);
   $output .= '</div>';
   return $output;
 }
 
-function theme_rsvp_help($content) {
+function theme_rsvp_help($content = NULL) {
   return '<div id="help">'. $content .'</div>';
 }
 
-function theme_rsvp_invite_mail_subject($invite) {
+function theme_rsvp_invite_mail_subject($invite = NULL, $subject = NULL) {
    $site = variable_get("site_name", "drupal");
-   $subject = $site ." - ". t('Event Invitation');
+   $subject = "[" . check_plain($site) ."] ". t('Event Invitation - ') . check_plain($subject);
    return $subject;
 }
      
-function theme_rsvp_invite_mail($invite) {
+function theme_rsvp_invite_mail($invite = NULL) {
   global $user;
   $site = variable_get("site_name", "drupal");
-  $body = t("Hello!\n\nYou have been invited to attend an event by !owner at !site.\n\nYou can view the event itself by following this link: \n!eventurl\n\nYou can view the full invitation by following this link: \n!url\n\nHere is the invitation message:\n", array('!owner'=>$user->name, '!site'=>$site, '!eventurl'=>url("node/$invite->nid", NULL, NULL, 1), '!url'=>url("rsvp/email/$invite->hash", NULL, NULL, 1))) .$invite->invite_text;
+  $body = t("Hello !uname!!nl!nlYou have been invited to attend an event by !owner at !site.!nl!nlYou can view the event itself by following this link: !nl!eventurl!nl!nlYou can view the full invitation, reply and add a comment by following this link: !nl!url!nl!nlPlease do not reply to this email.!nl!nlHere is the invitation message:!nl", array('!nl' => '<br />','!owner'=>$user->name, '!site'=>$site, '!uname'=>_rsvp_getAttendeeEmail($invite, true) , '!eventurl'=>url("node/$invite->nid", array('absolute'=>true)), '!url'=>url("rsvp/email/$invite->hash/view", array('absolute'=>true)))) . check_markup($invite->invite_text);
   return $body;
 }
+
+function theme_rsvp_message_mail_subject($invite = NULL, $subject = NULL) {
+   $site = variable_get("site_name", "drupal");
+   $subject = "[" . check_plain($site) ."] ". check_plain($subject);
+   return $subject;
+}
+
+function theme_rsvp_message_mail($invite = NULL, $sender = NULL, $body = NULL) {
+  global $user;
+  $site = variable_get("site_name", "drupal");
+  $body = t("Hello !uname!!nl!nlYou have been sent a message by !sender at !site.!nl!nlYou can view the invitation from where it originated by following this link: !nl!url!nl!nlHere is the message:!nl", array('!sender' => $sender, '!site' => $site, '!uname' =>_rsvp_getAttendeeEmail($invite, true), '!nl' => '<br />', '!url' => url("rsvp/email/$invite->hash/view", array('absolute' => TRUE)))) . check_markup($body);
+
+  return $body;
+}
+
+
  /** @} End of addtogroup themeable */
-?>
+
Index: rsvp.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rsvp/rsvp.install,v
retrieving revision 1.5
diff -u -r1.5 rsvp.install
--- rsvp.install	9 Mar 2008 21:05:09 -0000	1.5
+++ rsvp.install	16 Nov 2008 04:56:58 -0000
@@ -6,8 +6,9 @@
 }
 
 function rsvp_schema() {
+
   $schema['rsvp'] = array(
-    'descriptions' => t('RSVP contents'),
+    'description' => t('RSVP contents'),
     'fields' => array(
       'rid' => array(
         'description' => ('The primary identifier'),
@@ -39,8 +40,16 @@
         'description' => ('RSVP body'),
         'type' => 'text',
       ),
-      'blind' => array(
-        'description' => ('Defines whether invited users are visible or not'),
+      'response_blind' => array(
+        'description' => ('Defines whether responses (result) of rsvp is visible or not, and when it becomes visible.'),
+        'type' => 'int',
+        'size' => 'tiny',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => '0'
+      ),
+      'attendees_visible' => array(
+        'description' => ('Defines whether attendees are visible to other users or not, and when they become visible'),
         'type' => 'int',
         'size' => 'tiny',
         'unsigned' => TRUE,
@@ -66,17 +75,23 @@
       'timestamp' => array(
         'description' => ('Records the last update time'),
         'type' => 'int',
-        'size' => 'medium',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => '0'
+      ),
+      'startdate' => array(
+        'description' => ('The startdate related to this invitation'),
+        'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => '0'
       ),
     ),
-    'primary key' => array('rid', 'nid', 'uid')
+    'primary key' => array('rid', 'nid', 'uid'),
   );
 
   $schema['rsvp_invite'] = array(
-    'descriptions' => t('RSVP invitation status'),
+    'description' => t('RSVP invitation status'),
     'fields' => array(
       'response' => array(
         'description' => ('Response of the invitee'),
@@ -129,22 +144,137 @@
       'timestamp' => array(
         'description' => ('Records the last update time'),
         'type' => 'int',
-        'size' => 'medium',
         'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => '0'
       ),
+      'comment' => array(
+        'description' => ('Response Comment'),
+        'type' => 'text',
+      ),
+      
     ),
-    'primary key' => array('rid', 'email', 'uid')
+    'primary key' => array('rid', 'email', 'uid'),
   );
 
   // check the event module weight:
   $event_weight = db_result(db_query("SELECT weight FROM {system} WHERE name = 'event'"));
-  // make RSVP execute after event:
-  db_query("UPDATE {system} SET weight = %d+1 WHERE name = 'rsvp'", $event_weight);
+  // check the date module weight:
+  $date_weight = db_result(db_query("SELECT weight FROM {system} WHERE name = 'date'"));
+  // make RSVP execute after event/date:
+  db_query("UPDATE {system} SET weight = %d+1 WHERE name = 'rsvp'", max($event_weight, $date_weight));
+
+  return $schema;
 }
 
 function rsvp_uninstall() {
   drupal_uninstall_schema('rsvp');
+
+  variable_del('rsvp_connector');
+  variable_del('rsvp_content_types');
+  variable_del('rsvp_from_address');  
+}
+
+/**
+ * Addition of node version to simplenews_newsletters in order to record the
+ * node version which is being send.
+ */
+function rsvp_update_6000() {
+
+  $ret = array();
+  
+  db_add_field($ret, 'rsvp', 'startdate', array(
+        'description' => ('The startdate related to this invitation'),
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => '0'
+      )
+  );
+
+  db_change_field($ret, 'rsvp', 'timestamp', 'timestamp', array(
+        'description' => ('Records the last update time'),
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => '0'
+      )
+  );
+
+  db_change_field($ret, 'rsvp', 'blind', 'response_blind', array(
+        'description' => ('Defines whether responses (result) of rsvp is visible or not, and when it becomes visible.'),
+        'type' => 'int',
+        'size' => 'tiny',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => '0'
+      )
+  );
+  
+  db_add_field($ret, 'rsvp', 'attendees_visible', array(
+        'description' => ('Defines whether attendees are visible to other users or not, and when they become visible'),
+        'type' => 'int',
+        'size' => 'tiny',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => '0'
+      )
+  );
+  
+  
+  db_change_field($ret, 'rsvp_invite', 'timestamp', 'timestamp', array(
+        'description' => ('Records the last update time'),
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => '0'
+      )
+      
+  );
+
+  db_add_field($ret, 'rsvp_invite', 'comment', array(
+        'description' => ('Response Comment'),
+        'type' => 'text',
+        )
+  );
+  
+  return $ret;
+	
+}
+
+
+
+/**
+ * Implementation of hook_requirements().
+ * Make sure module Event or module Date is enabled.
+ */
+function rs_vp_requi_rements($phase) {
+  $requirements = array();
+
+  $t = get_t();
+
+
+  switch ($phase) {
+    case 'runtime':
+      $event=module_exists('rsvp_eventconnector');
+      $date=module_exists('rsvp_dateconnector');
+      $error = FALSE;
+      if ($event = FALSE && $date = FALSE) {
+        $error = TRUE;
+        $severity = REQUIREMENT_ERROR;
+        $value = $t('The RSVP module requires that at least one rsvp connector module is enabled.', array('!link' => l($t('RSVP'), 'admin/build/modules')));
+      }
+      if ($error) {
+        $requirements['connector'] = array(
+          'title' => $t('RSVP requirements'),
+          'value' => $value,
+          'severity' => $severity,
+          );
+      }
+      break;
+     case 'install':
+      break;
+  }
+  return $requirements;
 }
 
Index: rsvp.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rsvp/rsvp.info,v
retrieving revision 1.5
diff -u -r1.5 rsvp.info
--- rsvp.info	9 Mar 2008 21:05:09 -0000	1.5
+++ rsvp.info	16 Nov 2008 04:56:58 -0000
@@ -1,6 +1,5 @@
 ;$Id: rsvp.info,v 1.5 2008/03/09 21:05:09 owahab Exp $
 name = RSVP
-description = Provides rsvp functionality for node types enabled in the event system.
-package = Event
-dependencies[] = event
+description = Provides rsvp functionality.
+package = RSVP
 core = 6.x
Index: contrib/rsvp_views/rsvp_views.module
===================================================================
RCS file: contrib/rsvp_views/rsvp_views.module
diff -N contrib/rsvp_views/rsvp_views.module
--- contrib/rsvp_views/rsvp_views.module	31 Aug 2007 23:41:08 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,101 +0,0 @@
-<?php
-/** 
-* $Id: rsvp_views.module,v 1.2 2007/08/31 23:41:08 owahab Exp $
-* @file rsvp_views.module
-* @brief Views integration for RSVP module
-* @author  Omar Abdel-Wahab
-* @date 2007-08-31
- */
-
-/** 
-* Declare rsvp tables to views.
-* 
-* @return array of tables.
- */
-function rsvp_views_tables() {
-  $tables['rsvp'] = array(
-    'name' => 'rsvp',
-    'provider' => 'rsvp',
-    'join' => array(
-      'type' => 'inner',
-      'left' => array(
-        'table' => 'node',
-        'field' => 'nid'
-      ),
-      'right' => array(
-        'field' => 'nid'
-      )
-    ),
-    'fields' => array(
-      'total_rsvps' => array(
-        'name' => t('RSVP: Total RSVPs'),
-        'sortable' => TRUE,
-        'notafield' => TRUE,
-        'query_handler' => 'views_query_handler_field_rsvp_total_rsvps',
-        'help' => t('Display total RSVPs for the node.'),
-      ),
-    ),
-    'sorts' => array(
-      'total_rsvp' => array(
-        'name' => t('RSVP: Total RSVPs'),
-        'handler' => 'views_rsvp_sort_handler_total_rsvp',
-        'help' => t('Sort by the total RSVPs on a node'),
-      ),
-    ),
-  );
-  $tables['rsvp_invite'] = array(
-    'name' => 'rsvp_invite',
-    'provider' => 'rsvp',
-    'join' => array(
-      'left' => array(
-        'table' => 'rsvp',
-        'field' => 'rid'
-      ),
-      'right' => array(
-        'field' => 'rid'
-      )
-    ),
-    'fields' => array(
-      'total_invites' => array(
-        'name' => t('RSVP: Total Invites'),
-        'sortable' => TRUE,
-        'notafield' => TRUE,
-        'query_handler' => 'views_query_handler_field_rsvp_total_invites',
-        'help' => t('Display total invites for all RSVPs on the node.'),
-      ),
-    ),
-    'sorts' => array(
-      'total_invites' => array(
-        'name' => t('RSVP: Total Invites'),
-        'help' => t('Sort by the total invites in all RSVPs on a node'),
-      ),
-    ),
-  );
-
-  return $tables;
-}
-
-/**
- * Handler for total RSVPs field.
- */
-function views_query_handler_field_rsvp_total_rsvps($fielddata, $fieldinfo, &$query) {
-  $query->ensure_table('rsvp');
-  $query->add_field('COUNT(DISTINCT rsvp.rid)', '', $fielddata['tablename'] . '_total_rsvps');
-  $query->groupby[] = 'rsvp.nid';
-  $query->count_field = 'rsvp.nid';
-}
-
-/**
- * Handler for total invites field.
- */
-function views_query_handler_field_rsvp_total_invites($fielddata, $fieldinfo, &$query) {
-  $query->ensure_table('rsvp_invite');
-  $query->add_field('COUNT(rsvp_invite.hash)', '', $fielddata['tablename'] . '_total_invites');
-  $query->groupby[] = 'rsvp.nid';
-}
-
-function views_rsvp_sort_handler_total_rsvp($action, &$query, $sortinfo, $sort) {
-  $query->orderby[] = "rsvp.rsvp_total_rsvps $sort[sortorder]";
-}
-
-?>
Index: contrib/rsvp_views/rsvp_views.info
===================================================================
RCS file: contrib/rsvp_views/rsvp_views.info
diff -N contrib/rsvp_views/rsvp_views.info
--- contrib/rsvp_views/rsvp_views.info	31 Aug 2007 23:41:08 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,5 +0,0 @@
-;$Id: rsvp_views.info,v 1.2 2007/08/31 23:41:08 owahab Exp $
-name = RSVP Views
-description = "Provides RSVP integration with views module."
-package = "Event"
-dependencies = rsvp views
Index: rsvp_handler_field_rsvp_invite_total_invites.inc
===================================================================
RCS file: rsvp_handler_field_rsvp_invite_total_invites.inc
diff -N rsvp_handler_field_rsvp_invite_total_invites.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rsvp_handler_field_rsvp_invite_total_invites.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,23 @@
+<?php
+// $Id$
+
+/**
+ * Handler for total invites field.
+ */
+
+class rsvp_handler_field_rsvp_invite_total_invites extends views_handler_field {
+
+  function query() {
+
+    $this->ensure_my_table();
+    $formula = 'COUNT(' . $this->table_alias . '.hash' . ')';
+    $this->query->add_field(NULL, $formula, $this->table_alias . '_total_invites');
+    $this->query->add_groupby('rsvp.nid');
+  }
+    
+  function render($values) {
+
+    $item = !empty($values->{$this->table_alias . '_total_invites'}) ? $values->{$this->table_alias . '_total_invites'} : 0;
+    return $item;
+  }
+}
Index: rsvp_dateconnector.module
===================================================================
RCS file: rsvp_dateconnector.module
diff -N rsvp_dateconnector.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rsvp_dateconnector.module	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,133 @@
+<?php
+// $Id$
+
+class RsvpDateConnectorImpl extends RsvpConnectorImpl {
+
+  //returns a date as int in unix form (and converted to UTC).
+  function convert_date2UTCUnix($dateAsString, $timezone, $date_type)
+  { 
+  	//1) convert input date into DateTime 
+  	$date = date_make_date($dateAsString, $timezone, $date_type);
+  	
+  	//2) convert DateTime into UTC
+    date_timezone_set($date, timezone_open('UTC')); 	
+  	
+    //3) convert DateTime into Unix
+    return intval(date_convert($date, DATE_OBJECT, DATE_UNIX));
+  }	
+
+  function get_datecount($node, $field) {
+  	$fld = $node->$field;
+  	
+  	return count($fld);
+  }
+
+  //returns startdate as unix timestamp in utc 
+  function get_startdate($node, $field, $pos) {    
+  	$fld = $node->$field;
+
+    $timezoneName_db = $this->get_offset_db($node, $field, $pos);
+  	
+    $date = $this->convert_date2UTCUnix($fld[$pos]['value'], $timezoneName_db, $fld[$pos]['date_type']);
+    return $date;
+  }
+
+  //returns startdate as string in local timezone
+  function get_startdateAsString($node, $field, $pos) {
+  	
+  	$fld = $node->$field;
+    
+    $timezoneName_db = $this->get_offset_db($node, $field, $pos);
+    //$timezoneName_target = $this->get_offset($node, $field, $pos);
+
+    //1) convert input date into DateTime 
+    $date = date_make_date($fld[$pos]['value'], $timezoneName_db, $fld[$pos]['date_type']);
+    
+    //2) convert DateTime into target timezone
+    $timezone_target = date_default_timezone();
+    
+    date_timezone_set($date, $timezone_target);     
+      
+    //3) convert DateTime into String
+    $format = date_formatter_format('default', $field);
+    $out = date_format_date($date, 'custom', $format);
+    return $out;
+  }
+  
+  //returns enddate as unix timestamp in utc
+  function get_enddate($node, $field, $pos) {
+  	$fld = $node->$field;
+  	
+  	//if no "toDate" is set, return the "StartDate" of the event instead.
+  	if (!isset($fld[$pos]['value2'])) {
+  	  return $this->get_startdate($node, $field, $pos);
+  	}
+    
+  	$timezoneName_db = $this->get_offset_db($node, $field, $pos);
+  	
+  	
+    $date = $this->convert_date2UTCUnix($fld[$pos]['value2'], $timezoneName_db, $fld[$pos]['date_type']);
+    return $date;
+  }
+  
+  //returns the position for a particular hash, or -1 if invalid hash
+  function get_posByHash($node, $field, $hash) {
+    $fld = $node->$field;
+    
+    $count = $this->get_datecount($node, $field);
+
+    for ($i = 0; $i < $count; $i++) {
+      $unixdate = $this->get_startdate($node, $field, $i);
+      if ($unixdate == $hash) {
+      	return $i;
+      }
+    }
+    return -1;
+  }
+  
+  /*
+   * PRIVATE METHOD. Do not use outside. Return type is based on used connector.
+   * returns time zone offset according to Date API. 
+   */
+  function get_offset($node, $field, $pos) {
+    $fld = $node->$field;
+    
+    return $fld[$pos]['timezone'];
+  }
+
+  /*
+   * PRIVATE METHOD. Do not use outside. Return type is based on used connector.
+   * returns time zone name as date is stored in database according to Date API. 
+   */
+  function get_offset_db($node, $field, $pos) {
+    $fld = $node->$field;
+    
+    return $fld[$pos]['timezone_db'];
+  }
+  
+  function is_event_enabled($contenttype) {
+
+    $rsvp_content_types = variable_get('rsvp_content_types', array());
+    if (!isset ($rsvp_content_types[$contenttype])) {
+      return false;
+    }
+    else {
+      return true;
+    }
+  }
+  
+  function isTypesAreSelectable() {
+    return true;
+  }
+  
+  //returns true if the connector supports multiple fields per content-type. (e.g. Repeatable dates in Date API).
+  function hasMultipleFields() {
+    return true;
+  }
+  
+  
+}
+
+function rsvp_dateconnector_getconnector() {
+  return new RsvpDateConnectorImpl();  
+}
Index: .project
===================================================================
RCS file: .project
diff -N .project
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ .project	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>rsvpnew</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.php.core.PhpIncrementalProjectBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.php.core.ValidationManagerWrapper</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.php.core.PHPNature</nature>
+	</natures>
+</projectDescription>
Index: rsvp_eventconnector.install
===================================================================
RCS file: rsvp_eventconnector.install
diff -N rsvp_eventconnector.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rsvp_eventconnector.install	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,45 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_install().
+ */
+function rsvp_eventconnector_install() {
+
+  // check the rsvp module weight:
+  $rsvp_weight = db_result(db_query("SELECT weight FROM {system} WHERE name = 'rsvp'"));
+  // make rsvp_eventconnector execute after rsvp:
+  db_query("UPDATE {system} SET weight = %d+1 WHERE name = 'rsvp_eventconnector'", $rsvp_weight);
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function rsvp_eventconnector_uninstall() {
+
+  db_query('DELETE FROM {rsvp}');
+  db_query('DELETE FROM {rsvp_invite}');
+    
+  variable_del('rsvp_content_types'); 
+}
+
+/**
+ * Implementation of hook_enable().
+ */
+function rsvp_eventconnector_enable() {
+  variable_set('rsvp_connector', 'event');
+  variable_set('rsvp_content_types', array('event' => ''));    
+}
+
+/**
+ * Implementation of hook_disable().
+ */
+function rsvp_eventconnector_disable() {
+  $connector = variable_get('rsvp_connector', NULL);
+  //This disable func is being called preventive even if other modules are being modified.
+  //Delete variable only if we set it.
+  if (isset($connector) && $connector == 'event' ) { 
+    variable_del('rsvp_connector');
+  }
+}
+
Index: rsvp_handler_field_rsvp_total_rsvps.inc
===================================================================
RCS file: rsvp_handler_field_rsvp_total_rsvps.inc
diff -N rsvp_handler_field_rsvp_total_rsvps.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rsvp_handler_field_rsvp_total_rsvps.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,27 @@
+<?php
+// $Id$
+
+
+
+
+/**
+ * Handler for total RSVPs field.
+ */
+
+class rsvp_handler_field_rsvp_total_rsvps extends views_handler_field {
+
+  function query() {
+
+  	$this->ensure_my_table();
+    $formula = 'COUNT(DISTINCT ' . $this->table_alias . '.rid)';
+    $this->query->add_field(NULL, $formula, $this->table_alias . '_total_rsvps');
+    $this->query->add_groupby('nid');
+  }
+	
+  function render($values) {
+
+    $item = !empty($values->{$this->table_alias . '_total_rsvps'}) ? $values->{$this->table_alias . '_total_rsvps'} : 0;
+    return $item;
+  }
+}
+
Index: rsvp_eventconnector.module
===================================================================
RCS file: rsvp_eventconnector.module
diff -N rsvp_eventconnector.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rsvp_eventconnector.module	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,75 @@
+<?php
+// $Id$
+
+class RsvpEventConnectorImpl extends RsvpConnectorImpl {
+
+  //returns a unix date (int) as String. (and already converted to the correct timezone).
+//  function print_unixDateAsString($unixdate)
+//  {  
+//    return $unixdate;
+//  } 
+	
+  function get_datecount($node, $field) {
+    return 1;
+  }
+	
+  //returns startdate as unix timestamp in utc
+  function get_startdate($node, $field, $pos) {
+    $eventstart = $node->event['start'];
+    $unixutc = strtotime($eventstart);
+      	
+    return $unixutc;
+  }
+
+  //startdate as string in local timezone
+  function get_startdateAsString($node, $field, $pos) {
+    
+    return $node->event['start'];    
+  }
+  
+  //returns enddate as unix timestamp in utc
+  function get_enddate($node, $field, $pos) {
+    $eventend = $node->event['end'];
+    $unixutc = strtotime($eventend);
+    $r1 = date('r', $unixutc);
+    return $unixutc;
+  }
+  
+  /*
+   * PRIVATE METHOD. Do not use outside. Return type is based on used connector.
+   * returns time zone offset according to Event API. 
+   */
+    function get_offset($node, $field, $pos) {
+    return $node->event['offset'];
+  }
+  
+  //returns the position for a particular hash, or -1 if invalid hash
+  function get_posByHash($node, $field, $hash) {
+  	//event node has only one start_date
+    return 0;
+  }
+  
+  function is_event_enabled($contenttype) {
+  	
+    $rsvp_content_types = variable_get('rsvp_content_types', array());
+    if (!isset ($rsvp_content_types['event'])) {
+      return false;
+    }
+  	
+    return event_is_enabled($contenttype);
+  }
+  
+  function isTypesAreSelectable() {
+    return false;
+  }
+  
+  //returns true if the connector supports multiple fields per content-type. (e.g. Repeatable dates in Date API).
+  function hasMultipleField() {
+    return false;
+  }
+  
+}
+
+function rsvp_eventconnector_getconnector() {
+  return new RsvpEventConnectorImpl();  
+}
Index: rsvp.views.inc
===================================================================
RCS file: rsvp.views.inc
diff -N rsvp.views.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rsvp.views.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,119 @@
+<?php
+// $Id$
+
+/**
+ * @module rsvp
+ * @package rsvp - A drupal module developed for civicspace - a distribution of drupal.
+ * @description Provides view support for rsvp.
+ * @author crunchywelch (welch@advomatic.com)
+ * @author Omar Abdel-Wahab (owahab@gmail.com)
+ * @author Ulf Schenk (ulf@schenkunlimited.net)
+ *
+ */
+
+/** 
+* Declare rsvp tables to views.
+* 
+* @return array of tables.
+ */
+function rsvp_views_data() {
+  
+	$data = array(
+      'rsvp' => array(
+        'table' => array(
+          'group' => t('RSVP'),
+    
+          'join' => array(
+            'node' => array(
+              'left_field' => 'nid',
+              'field' => 'nid',
+              'type' => 'INNER',
+            ),
+          ),
+        ),
+        'total_rsvps' => array(
+          'title' => t(' Total RSVPs'),
+          'help' => t('Display total RSVPs for the node.'),
+          'field' => array(
+            'handler' => 'rsvp_handler_field_rsvp_total_rsvps',
+            'click sortable' => true,
+          ),
+//          'sort' => array(
+//            'handler' => 'views_rsvp_sort_handler_total_rsvp',
+//          'help' => t('Sort by the total RSVPs on a node'),
+//        ),
+        
+        ),  
+    
+      ),
+	
+	  'rsvp_invite' => array(
+        'table' => array(
+          'group' => t('RSVP'),
+	      'base' => array(
+	        'field' => 'rid',
+            'title' => t('RSVP'),
+            'help' => t('Displaying rsvp'),
+	      ),
+	
+          'join' => array(
+            'node' => array(
+              'left_table' => 'rsvp',
+	          'left_field' => 'rid',
+              'field' => 'rid',
+            ),
+            'rsvp' => array(
+              'left_field' => 'rid',
+              'field' => 'rid',
+            ),
+          ),
+        ),
+        'total_invites' => array(
+          'title' => t('Total Invites'),
+          'help' => t('Display total invites for all RSVPs on the node.'),
+          'field' => array(
+            'handler' => 'rsvp_handler_field_rsvp_invite_total_invites',
+            'click sortable' => true,
+          ),
+/*          'sort' => array(
+            'help' => t('Sort by the total invites in all RSVPs on a node'),
+          ),
+*/
+        ),    
+      
+      ),
+	
+	
+	
+	  
+	  
+    );
+	
+    return $data;
+	
+}
+
+function rsvp_views_handlers() {
+  return array(
+    'handlers' => array(
+      'rsvp_handler_field_rsvp_total_rsvps' => array(
+        'parent' => 'views_handler_field',
+      ),
+      'rsvp_handler_field_rsvp_invite_total_invites' => array(
+        'parent' => 'views_handler_field',
+      ),
+/*      'rsvp_handler_field_rsvp_invite_total_invites' => array(
+        'parent' => 'views_handler_filter_in_operator',
+      ),
+*/    ),
+  );
+}
+
+
+
+///////////////////
+
+/*function views_rsvp_sort_handler_total_rsvp($action, &$query, $sortinfo, $sort) {
+  $query->orderby[] = "rsvp.rsvp_total_rsvps $sort[sortorder]";
+}
+*/
Index: rsvp_dateconnector.install
===================================================================
RCS file: rsvp_dateconnector.install
diff -N rsvp_dateconnector.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rsvp_dateconnector.install	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,44 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_install().
+ */
+function rsvp_dateconnector_install() {
+
+  // check the rsvp module weight:
+  $rsvp_weight = db_result(db_query("SELECT weight FROM {system} WHERE name = 'rsvp'"));
+  // make rsvp_dateconnector execute after rsvp:
+  db_query("UPDATE {system} SET weight = %d+1 WHERE name = 'rsvp_dateconnector'", $rsvp_weight);
+
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function rsvp_dateconnector_uninstall() {
+
+  db_query('DELETE FROM {rsvp}');
+  db_query('DELETE FROM {rsvp_invite}');
+	
+  variable_del('rsvp_content_types'); 
+}
+
+/**
+ * Implementation of hook_enable().
+ */
+function rsvp_dateconnector_enable() {
+  variable_set('rsvp_connector', 'date');
+}
+
+/**
+ * Implementation of hook_disable().
+ */
+function rsvp_dateconnector_disable() {
+  $connector = variable_get('rsvp_connector', NULL);
+  //This disable func is being called preventive even if other modules are being modified.
+  //Delete variable only if we set it.
+  if (isset($connector) && $connector == 'date' ) {	
+	variable_del('rsvp_connector');
+  }
+}
Index: rsvp_eventconnector.info
===================================================================
RCS file: rsvp_eventconnector.info
diff -N rsvp_eventconnector.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rsvp_eventconnector.info	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,7 @@
+; $Id$
+name = RSVP event connector
+description = Provides rsvp functionality for node type event.
+package = RSVP
+dependencies[] = rsvp
+dependencies[] = event
+core = 6.x
Index: rsvp_dateconnector.info
===================================================================
RCS file: rsvp_dateconnector.info
diff -N rsvp_dateconnector.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rsvp_dateconnector.info	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,7 @@
+; $Id$
+name = RSVP date connector
+description = Provides rsvp functionality for node types enabled by the Date/Date API module.
+package = RSVP
+dependencies[] = rsvp
+dependencies[] = date
+core = 6.x
