diff -urp signup/modules/signup_webform/README.txt signup/modules/signup_webform/README.txt
--- signup/modules/signup_webform/README.txt	2010-10-18 14:42:11.000000000 -0700
+++ signup/modules/signup_webform/README.txt	2010-10-22 11:15:49.000000000 -0700
@@ -1,4 +1,4 @@
-$Id: README.txt,v 1.1.2.1 2010/10/18 21:42:11 joachim Exp $
+$Id$
 
 The signup webform module provides a signup pane for each webform node. This allows  users to quickly create a form to collect data specific to a signup event.
 
diff -urp signup/modules/signup_webform/signup_webform.info signup/modules/signup_webform/signup_webform.info
--- signup/modules/signup_webform/signup_webform.info	2010-10-18 17:19:06.000000000 -0700
+++ signup/modules/signup_webform/signup_webform.info	2010-10-22 11:15:50.000000000 -0700
@@ -1,14 +1,7 @@
-; $Id: signup_webform.info,v 1.1.2.1 2010/10/18 21:42:11 joachim Exp $
+; $Id$
 name = Signup webform
 description = Provides a signup form panes for each webform.
 dependencies[] = signup
 dependencies[] = webform
 package = Signup
 core = 6.x
-
-; Information added by drupal.org packaging script on 2010-10-19
-version = "6.x-2.x-dev"
-core = "6.x"
-project = "signup"
-datestamp = "1287447546"
-
diff -urp signup/modules/signup_webform/signup_webform.install signup/modules/signup_webform/signup_webform.install
--- signup/modules/signup_webform/signup_webform.install	2010-10-18 14:42:11.000000000 -0700
+++ signup/modules/signup_webform/signup_webform.install	2010-10-22 13:35:25.000000000 -0700
@@ -1,7 +1,8 @@
 <?php
-// $Id: signup_webform.install,v 1.1.2.1 2010/10/18 21:42:11 joachim Exp $
+// $Id$
 /**
- * @file signup_webform.install
+ * @file
+ * Install file for signup_webform
  */
 
 /**
@@ -38,7 +39,7 @@ function signup_webform_schema() {
     ),
     'primary key' => array('signup_sid', 'webform_nid'),
   );
-  
+
   return $schema;
 }
 
@@ -57,4 +58,3 @@ function signup_webform_uninstall() {
   // Remove tables.
   drupal_uninstall_schema('signup_webform');
 }
-
diff -urp signup/modules/signup_webform/signup_webform.module signup/modules/signup_webform/signup_webform.module
--- signup/modules/signup_webform/signup_webform.module	2010-10-18 14:42:11.000000000 -0700
+++ signup/modules/signup_webform/signup_webform.module	2010-10-24 01:50:42.000000000 -0700
@@ -1,12 +1,11 @@
 <?php
-// $Id: signup_webform.module,v 1.1.2.1 2010/10/18 21:42:11 joachim Exp $
+// $Id$
 /**
- * @file signup_webform.module
- * 
- * Signup integration with webform module: provides a signup pane for each 
+ * @file
+ * Signup integration with webform module: provides a signup pane for each
  * webform node.
  *
- * The intention is that if a webform is used for signup, it is *not* also 
+ * The intention is that if a webform is used for signup, it is *not* also
  * used as a standalone webform; rather, we make use of webform for its
  * convenience in allowing users to use a UI to build a form.
  *
@@ -31,7 +30,7 @@
  * The callback should have the following signature:
  *   function my_callback(&$signup_form, &$form_state, $node, $signup, $pane_id, $signup_type = 'auth')
  * See signup_basic_form_form for an example.
- * The values submitted to the form elements defined by this form will be 
+ * The values submitted to the form elements defined by this form will be
  * serialized and stored in the {signup_log} table as 'form_data'.
  *
  * @param $node
@@ -40,33 +39,66 @@
  *  panes if the node satisfies certain properties.
  *
  * @return
- *   An array of possible forms, keyed by a unique ID. Each value is itself an 
+ *   An array of possible forms, keyed by a unique ID. Each value is itself an
  *   array of data, with the following key-value pairs:
  *     - 'label': (required) The human-readable name of the form.
  *     - 'description': (required) Extra information about the form.
  *     - 'callback': (required) The name of a function.
- *     - 'operations': (optional) A list of links for the user to perform 
+ *     - 'operations': (optional) A list of links for the user to perform
  *        administrative tasks on this pane, either global or per-node settings.
  *        The format is an unkeyed array of link arrays (suitable for passing
  *        to theme_links).
  *        You may use %nid as a token in your link's href property to
- *        insert the node id of the current signup node. 
+ *        insert the node id of the current signup node.
  *        The following optional keys are also available:
  *        - destination: if set to TRUE, the return destination will be appended
  *          to the link as a query string with drupal_get_destination, allowing
  *          the user to return to this page directly. Do not use if your link
  *          sends the user to a complex series of forms or pages.
- *        - not_defaults: if set to TRUE, this link will not be shown when 
+ *        - not_defaults: if set to TRUE, this link will not be shown when
  *          default signup settings are being edited at admin/settings/signup.
- *          Use this when your settings link would be meaningless in this 
+ *          Use this when your settings link would be meaningless in this
  *          context because it is dependent on the current node.
  *
- * @see signup_basic_form_form.
+ * @see signup_basic_form_form()
  */
+
+function signup_webform_webform3() {
+  // Check if this is Webform 6.3x
+  // Make sure the installation API is available before running drupal_get_installed_schema_version()
+  include_once './includes/install.inc';
+  return drupal_get_installed_schema_version('webform') > 6300 ? TRUE : FALSE;
+}
+
 function signup_webform_signup_pane_info($node = NULL) {
   // Get the webform nodes.
-  $result = db_query('SELECT n.title, n.nid FROM {node} n WHERE n.type = "webform" AND n.status = 1');
+  $result = db_query(db_rewrite_sql('SELECT n.title, n.nid FROM {node} n WHERE n.type = "webform" AND n.status = 1'));
   while ($webform = db_fetch_object($result)) {
+    if (signup_webform_webform3()) {
+    $panes['webform_' . $webform->nid] = array(
+      'label' => 'Webform: ' . $webform->title,
+      'description' => t('Collects data for the webform.'),
+      'callback' => 'signup_webform_form',
+      'operations' => array(
+        array(
+          'href'  => 'node/' . $webform->nid . '/webform',
+          'title' => 'Edit webform components',
+          'destination' => TRUE,
+        ),
+        array(
+          'href'  => 'node/' . $webform->nid . '/webform/configure',
+          'title' => 'Edit webform settings',
+          'destination' => TRUE,
+        ),
+        array(
+          'href'  => 'node/' . $webform->nid . '/webform/emails',
+          'title' => 'Edit webform emails',
+          'destination' => TRUE,
+        ),
+      ),
+    );
+    }
+    else {
     $panes['webform_' . $webform->nid] = array(
       'label' => 'Webform: ' . $webform->title,
       'description' => t('Collects data for the webform.'),
@@ -84,8 +116,9 @@ function signup_webform_signup_pane_info
         ),
       ),
     );
+    }
   }
-  
+
   return $panes;
 }
 
@@ -100,7 +133,7 @@ function signup_webform_signup_pane_info
  * @param $node
  *   The fully loaded node object.
  * @param $signup
- *   If this is an existing signup, the fully loaded signup object. If this is a 
+ *   If this is an existing signup, the fully loaded signup object. If this is a
  *   new signup, this is just NULL.
  * @param $pane_id
  *   The pane ID being invoked. This allows a module to implement multiple panes
@@ -111,41 +144,197 @@ function signup_webform_signup_pane_info
  *    'anon' -- anonymous user signup form (includes required email field).
  *    'admin' -- admin form to signup another user (includes user selector).
  * @return
- *   A form API array for insertion into the signup form. 
+ *   A form API array for insertion into the signup form.
  */
 function signup_webform_form(&$signup_form, &$form_state, $node, $signup, $pane_id, $signup_type = 'auth') {
   $form = array();
-
   // Get the real nid from the prefixed pane ID and thence the node.
-  $webform_nid = substr($pane_id, 8);
+  $webform_nid = drupal_substr($pane_id, 8);
   $webform_node = node_load($webform_nid);
-  
-  module_load_include('inc', 'webform', 'webform_components');
-  webform_load_components();
-  
-  // Load the webform submission for existing signups, so the webform API
-  // takes care of putting in existing data.
-  if (isset($signup) && $signup_type != 'anon') {
-    $submission = signup_webform_get_signup_submission($signup, $webform_nid);
-  }  
-  
-  $component_tree = array();
-  $page_count = 1;
-  $page_num = 1;
-  _webform_components_tree_build($webform_node->webform['components'], $component_tree, 0, $page_count);
-  
-  //dsm($component_tree);
-
-  // Recursively add components to the form. Microweights keep things in webform order.
-  // No idea what most of these do; _webform_client_form_add_component() is an undocumented black box!
-  $microweight = 0.001;
-  $enabled = TRUE;
-  foreach ($component_tree['children'] as $cid => $component) {
-    // we have no existing values here ever.
-    $component_value = NULL;
-    _webform_client_form_add_component($cid, $component, $component_value, $form, $form, $submission, $page_num, $enabled);
+
+  if (signup_webform_webform3()) {
+    module_load_include('inc', 'webform', 'includes/webform.components');
+    global $user;
+
+    // Load the webform submission for existing signups, so the webform API
+    // takes care of putting in existing data.
+    if (isset($signup) && $signup_type != 'anon') {
+      $submission = signup_webform_get_signup_submission($signup, $webform_nid);
+    }
+
+    /**
+    * The following was extracted from webform_client_form().
+    */
+    // Bind arguments to $form to make them available in theming and form_alter.
+    $form['#node'] = $webform_node;
+    $form['#submission'] = $submission;
+    $form['#is_draft'] = $is_draft;
+    $form['#filter'] = $filter;
+
+    // Add a theme function for this form.
+    $form['#theme'] = array('webform_form_' . $webform_node->nid, 'webform_form');
+
+    // Add a css class for all client forms.
+    $form['#attributes'] = array('class' => 'webform-client-form');
+
+    // Set the encoding type (necessary for file uploads).
+    $form['#attributes']['enctype'] = 'multipart/form-data';
+
+    // Set the form action to the node ID in case this is being displayed on the
+    // teaser, subsequent pages should be on the node page directly.
+    if (empty($submission)) {
+      $form['#action'] = url('node/' . $webform_node->nid);
+    }
+
+    $form['#submit'] = array('webform_client_form_pages', 'webform_client_form_submit');
+    $form['#validate'] = array('webform_client_form_validate');
+
+    if (is_array($webform_node->webform['components']) && !empty($webform_node->webform['components'])) {
+      // Prepare a new form array.
+      $form['submitted'] = array(
+        '#tree' => TRUE
+      );
+      $form['details'] = array(
+        '#tree' => TRUE,
+      );
+
+      // Put the components into a tree structure.
+      if (!isset($form_state['storage']['component_tree'])) {
+        $form_state['webform']['component_tree'] = array();
+        $form_state['webform']['page_count'] = 1;
+        $form_state['webform']['page_num'] = 1;
+        _webform_components_tree_build($webform_node->webform['components'], $form_state['webform']['component_tree'], 0, $form_state['webform']['page_count']);
+      }
+      else {
+        $form_state['webform']['component_tree'] = $form_state['storage']['component_tree'];
+        $form_state['webform']['page_count'] = $form_state['storage']['page_count'];
+        $form_state['webform']['page_num'] = $form_state['storage']['page_num'];
+      }
+
+      // Shorten up our variable names.
+      $component_tree = $form_state['webform']['component_tree'];
+      $page_count = $form_state['webform']['page_count'];
+      $page_num = $form_state['webform']['page_num'];
+
+      // Recursively add components to the form.
+      foreach ($component_tree['children'] as $cid => $component) {
+        $component_value = isset($form_state['post']['signup_form_data'][$pane_id]['submitted'][$component['form_key']]) ? $form_state['post']['signup_form_data'][$pane_id]['submitted'][$component['form_key']] : NULL;
+        if (_webform_client_form_rule_check($webform_node, $component, $page_num, $form_state)) {
+          _webform_client_form_add_component($webform_node, $component, $component_value, $form['submitted'], $form, $form_state, $submission, 'form', $page_num, $filter);
+        }
+      }
+
+      // These form details help managing data upon submission.
+      $form['details']['nid'] = array(
+        '#type' => 'value',
+        '#value' => $webform_node->nid,
+      );
+      $form['details']['sid'] = array(
+        '#type' => 'hidden',
+        '#value' => isset($submission->sid) ? $submission->sid : '',
+      );
+      $form['details']['uid'] = array(
+        '#type' => 'value',
+        '#value' => isset($submission->uid) && !is_null($submission->uid) ? $submission->uid : $user->uid,
+      );
+      $form['details']['page_num'] = array(
+        '#type' => 'hidden',
+        '#value' => $page_num,
+      );
+      $form['details']['page_count'] = array(
+        '#type' => 'hidden',
+        '#value' => $page_count,
+      );
+      $form['details']['finished'] = array(
+        '#type' => 'hidden',
+        '#value' => isset($submission->is_draft) ? (!$submission->is_draft) : 0,
+      );
+      // Add the signup sid to the form
+      $form['details']['pane_id'] = array(
+        '#type' => 'hidden',
+        '#value' => $pane_id,
+      );
+      // Add buttons for pages, drafts, and submissions.
+      $form['actions'] = array(
+        '#tree' => FALSE,
+        '#weight' => 1000,
+        '#prefix' => '<div id="edit-actions" class="form-actions form-wrapper">',
+        '#suffix' => '</div>',
+      );
+
+      if ($page_count > 1) {
+        $next_page = t('Next Page >');
+        $prev_page = t('< Previous Page');
+
+        // Add the submit button(s).
+        if ($webform_node->webform['allow_draft'] && (empty($submission) || $submission->is_draft) && $user->uid != 0) {
+          $form['actions']['draft'] = array(
+            '#type' => 'submit',
+            '#value' => t('Save Draft'),
+            '#weight' => -2,
+            '#validate' => array(),
+          );
+        }
+
+        if ($page_num > 1) {
+          $form['actions']['previous'] = array(
+            '#type' => 'submit',
+            '#value' => $prev_page,
+            '#weight' => 5,
+            '#validate' => array(),
+          );
+        }
+
+        if ($page_num == $page_count) {
+          //$form['actions']['submit'] = array(
+          //  '#type' => 'submit',
+          //  '#value' => empty($webform_node->webform['submit_text']) ? t('Submit') : t($webform_node->webform['submit_text']),
+          //  '#weight' => 10,
+          //);
+        }
+        elseif ($page_num < $page_count) {
+          $form['actions']['next'] = array(
+            '#type' => 'submit',
+            '#value' => $next_page,
+            '#weight' => 10,
+          );
+        }
+      }
+      else {
+        // Add the submit button.
+        //$form['actions']['submit'] = array(
+        //  '#type' => 'submit',
+        //  '#value' => empty($webform_node->webform['submit_text']) ? t('Submit') : t($webform_node->webform['submit_text']),
+        //  '#weight' => 10,
+        //);
+      }
+    }
+  }
+  else {
+    module_load_include('inc', 'webform', 'webform_components');
+    webform_load_components();
+
+    // Load the webform submission for existing signups, so the webform API
+    // takes care of putting in existing data.
+    if (isset($signup) && $signup_type != 'anon') {
+      $submission = signup_webform_get_signup_submission($signup, $webform_nid);
+    }
+
+    $component_tree = array();
+    $page_count = 1;
+    $page_num = 1;
+    _webform_components_tree_build($webform_node->webform['components'], $component_tree, 0, $page_count);
+
+    // Recursively add components to the form. Microweights keep things in webform order.
+    // No idea what most of these do; _webform_client_form_add_component() is an undocumented black box!
+    $microweight = 0.001;
+    $enabled = TRUE;
+    foreach ($component_tree['children'] as $cid => $component) {
+      // we have no existing values here ever.
+      $component_value = NULL;
+      _webform_client_form_add_component($cid, $component, $component_value, $form, $form, $submission, $page_num, $enabled);
+    }
   }
-    
   return $form;
 }
 
@@ -155,14 +344,215 @@ function signup_webform_form(&$signup_fo
 function signup_webform_signup_data_alter(&$signup, $form_values) {
   // Act on each pane that is a webform pane.
   foreach (_signup_webform_pane_ids($signup->form_data) as $pane_id) {
-    // Load the webform API. 
+    // Load the webform API.
     // Do this inside the loop so signups that don't use webform don't load this.
-    module_load_include('inc', 'webform', 'webform_submissions');
-    
+    if (signup_webform_webform3()) {
+        module_load_include('inc', 'webform', 'includes/webform.submissions');
+    }
+    else {
+        module_load_include('inc', 'webform', 'webform_submissions');
+    }
+
     // Get the real nid from the prefixed pane ID and thence the node.
-    $webform_nid = substr($pane_id, 8);
+    $webform_nid = drupal_substr($pane_id, 8);
     $webform_node = node_load($webform_nid);
-          
+
+    $component_lookup = _signup_webform_translate_cid_form_keys($webform_node);
+
+    if (signup_webform_webform3()) {
+      // to do: check that the webform data has passed validation
+
+      $webform_data = $signup->form_data[$pane_id];
+      global $user;
+      $submitted_data = array();
+      $flipped_lookup = array_flip($component_lookup);
+      foreach ($flipped_lookup as $f_wf_key => $f_wf_data) {
+        foreach ($signup->form_data[$pane_id]['submitted'] as $wf_key => $wf_data) {
+          if ($wf_key === $f_wf_data) {
+            $submitted_data[$f_wf_key] = $wf_data;
+          }
+        }
+      }
+
+      // Create the submission object.
+      $submitted = (object) array(
+        'nid' => $webform_nid,
+        'uid' => $user->uid,
+        'sid' => $webform_data['details']['sid'],
+        'submitted' => time(),
+        'remote_addr' => ip_address(),
+        'is_draft' => FALSE,
+        'data' => webform_submission_data($webform_node, $submitted_data),
+      );
+
+      // Save the submission to the database.
+      if (empty($webform_data['details']['sid'])) {
+        // No sid was found thus insert it in the dataabase.
+        $webform_data['details']['sid'] = webform_submission_insert($webform_node, $submitted);
+        $webform_data['details']['is_new'] = TRUE;
+
+        // Set a cookie including the server's submission time.
+        // The cookie expires in the length of the interval plus a day to compensate for different timezones.
+        if (variable_get('webform_use_cookies', 0)) {
+          $cookie_name = 'webform-' . $webform_nid;
+          $time = time();
+          setcookie($cookie_name . '[' . $time . ']', $time, $time + $webform_node->webform['submit_interval'] + 86400);
+        }
+
+        // Save session information about this submission for anonymous users,
+        // allowing them to access or edit their submissions.
+        if (!$user->uid && user_access('access own webform submissions')) {
+          $_SESSION['webform_submission'][$webform_data['details']['sid']] = $webform_nid;
+        }
+      }
+      else {
+        // Sid was found thus update the existing sid in the database.
+        $submitted->sid = $webform_data['details']['sid'];
+        webform_submission_update($webform_node, $submitted);
+        $webform_data['details']['is_new'] = FALSE;
+      }
+
+      $sid = $webform_data['details']['sid'];
+
+      // Check if this form is sending an email.
+      if (!$is_draft && !$webform_data['details']['finished']) {
+        $submitted = webform_get_submission($webform_nid, $sid, TRUE);
+
+        // Create a themed message for mailing.
+        foreach ($webform_node->webform['emails'] as $eid => $email) {
+          // Pass through the theme layer if using the default template.
+          if ($email['template'] == 'default') {
+            $email['message'] = theme(array('webform_mail_' . $webform_nid, 'webform_mail', 'webform_mail_message'), $webform_node, $submitted, $email);
+          }
+          else {
+            $email['message'] = $email['template'];
+          }
+
+          // Replace tokens in the message.
+          $email['message'] = _webform_filter_values($email['message'], $webform_node, $submitted, $email, FALSE, TRUE);
+
+          // Build the e-mail headers.
+          $email['headers'] = theme(array('webform_mail_headers_' . $webform_nid, 'webform_mail_headers'), $webform_node, $submitted, $email);
+
+          // Assemble the FROM string.
+          if (isset($email['headers']['From'])) {
+            // If a header From is already set, don't override it.
+            $email['from'] = $email['headers']['From'];
+            unset($email['headers']['From']);
+          }
+          else {
+            $email['from'] = webform_format_email_address($email['from_address'], $email['from_name'], $webform_node, $submitted);
+          }
+
+          // Update the subject if set in the themed headers.
+          if (isset($email['headers']['Subject'])) {
+            $email['headers']['subject'] = $email['headers']['Subject'];
+            unset($email['headers']['Subject']);
+          }
+          else {
+            $email['subject'] = webform_format_email_subject($email['subject'], $webform_node, $submitted);
+          }
+
+          // Update the to e-mail if set in the themed headers.
+          if (isset($headers['To'])) {
+            $email['email'] = $headers['To'];
+            unset($headers['To']);
+          }
+
+          // Generate the list of addresses that this e-mail will be sent to.
+          $addresses = array_filter(explode(',', $email['email']));
+          $addresses_final = array();
+          foreach ($addresses as $address) {
+            $address = trim($address);
+
+            // After filtering e-mail addresses with component values, a single value
+            // might contain multiple addresses (such as from checkboxes or selects).
+            $address = webform_format_email_address($address, NULL, $webform_node, $submitted, TRUE, FALSE, 'short');
+
+            if (is_array($address)) {
+              foreach ($address as $new_address) {
+                $new_address = trim($new_address);
+                if (valid_email_address($new_address)) {
+                  $addresses_final[] = $new_address;
+                }
+              }
+            }
+            elseif (valid_email_address($address)) {
+              $addresses_final[] = $address;
+            }
+          }
+
+          // Mail the webform results.
+          foreach ($addresses_final as $address) {
+            // Verify that this submission is not attempting to send any spam hacks.
+            if (_webform_submission_spam_check($address, $email['subject'], $email['from'], $email['headers'])) {
+              watchdog('webform', 'Possible spam attempt from @remote_addr' . "<br />\n" . nl2br(htmlentities($email['message'])), array('@remote_add' => ip_address()));
+              drupal_set_message(t('Illegal information. Data not submitted.'), 'error');
+              return FALSE;
+            }
+
+            $language = $user->uid ? user_preferred_language($user) : language_default();
+            $mail_params = array(
+              'message' => $email['message'],
+              'subject' => $email['subject'],
+              'headers' => $email['headers'],
+              'node' => $webform_node,
+              'submission' => $submitted,
+            );
+            drupal_mail('webform', 'submission', $address, $language, $mail_params, $email['from']);
+          }
+
+        }
+      }
+
+      // Strip out empty tags added by WYSIWYG editors if needed.
+      $confirmation = drupal_strlen(trim(strip_tags($webform_node->webform['confirmation']))) ? $webform_node->webform['confirmation'] : '';
+      $redirect_url = trim($webform_node->webform['redirect_url']);
+
+      // Remove the domain name from the redirect.
+      $redirect_url = preg_replace('/^' . preg_quote($GLOBALS['base_url'], '/') . '\//', '', $redirect_url);
+
+      // Check confirmation and redirect_url fields.
+      $message = NULL;
+      $external_url = FALSE;
+      if ($is_draft) {
+        $redirect = NULL;
+        $message = t('Draft saved');
+      }
+      elseif (!empty($webform_data['details']['finished'])) {
+        $redirect = NULL;
+        $message = t('Submission updated.');
+      }
+      elseif (valid_url($redirect_url, TRUE)) {
+        $redirect = $redirect_url;
+        $external_url = TRUE;
+      }
+      elseif ($redirect_url && strpos($redirect_url, 'http') !== 0) {
+        $parts = parse_url($redirect_url);
+        $query = $parts['query'] ? ($parts['query'] . '&sid=' . $sid) : ('sid=' . $sid);
+        $redirect = array($parts['path'], $query, $parts['fragment']);
+      }
+      else {
+        $redirect = array('node/' . $webform_nid . '/done', 'sid=' . $sid);
+      }
+
+      // Show a message if manually set.
+      if (isset($message)) {
+        drupal_set_message($message);
+      }
+      // If redirecting and we have a confirmation message, show it as a message.
+      elseif (!$external_url && !empty($redirect_url) && !empty($confirmation)) {
+        drupal_set_message(check_markup($confirmation, $webform_node->webform['confirmation_format'], FALSE));
+      }
+
+      $form_state['redirect'] = $redirect;
+
+      $signup->form_data[$pane_id] = array(
+        'sid' => $sid,
+      );
+    }
+    else {
+
     /*
     So... some missing documentation!
     webform_submission_insert($node, $submitted)
@@ -171,21 +561,20 @@ function signup_webform_signup_data_alte
     *  (
     *      [1] => Array // Single checkbox TRUE/FALSE
     *          (
-    *              [1] => 1 
+    *              [1] => 1
     *          )
-    *  
+    *
     *      [2] => Abbey Road // Textfield
     *      [3] => Array // Multiple select: checkboxes
     *          (
     *              [John] => John
     *              [Paul] => Paul
     *          )
-    *  
+    *
     *  )
     *
     */
-    $component_lookup = _signup_webform_translate_cid_form_keys($webform_node);
-    
+
     $submitted = array();
     $webform_data = $signup->form_data[$pane_id];
     foreach ($webform_data as $form_key => $component_data) {
@@ -194,10 +583,10 @@ function signup_webform_signup_data_alte
       if (is_array($component_data)) {
         $component_data = array_filter($component_data);
       }
-      
+
       $submitted[$cid] = $component_data;
     }
-    
+
     if (isset($signup->sid)) {
       // existing signup: update the webform submission with the new data.
       $submission_sid = db_result(db_query('SELECT submission_sid FROM {signup_webform_submission} WHERE signup_sid = %d AND webform_nid = %d', $signup->sid, $webform_nid));
@@ -210,14 +599,15 @@ function signup_webform_signup_data_alte
     else {
       // new signup: insert webform submission.
       $sid = webform_submission_insert($webform_node, $submitted);
-      
+
       // Replace our data with just the submission ID; this is retrieved
-      // by signup_webform_signup_insert() once the signup is saved and has 
+      // by signup_webform_signup_insert() once the signup is saved and has
       // an ID.
       $signup->form_data[$pane_id] = array(
         'sid' => $sid,
       );
     }
+    }
   }
 }
 
@@ -233,7 +623,7 @@ function signup_webform_signup_insert($s
   foreach (_signup_webform_pane_ids($signup->form_data) as $pane_id) {
     // Retrieve the Submission id where we put it in the form data.
     $submission_sid = $signup->form_data[$pane_id]['sid'];
-    $webform_nid = substr($pane_id, 8);
+    $webform_nid = drupal_substr($pane_id, 8);
     db_query("INSERT INTO {signup_webform_submission} (signup_sid, webform_nid, submission_sid) VALUES (%d, %d, %d)", $signup->sid, $webform_nid, $submission_sid);
   }
 }
@@ -245,7 +635,7 @@ function signup_webform_signup_insert($s
  * a node's list of signups.
  *
  * We remove the submission ID that is internal data.
- * Since webform does not yet have view support, we add in the webform 
+ * Since webform does not yet have view support, we add in the webform
  * submission data.
  * @todo: Change all this when webform gets views support!
  *
@@ -261,13 +651,13 @@ function signup_webform_signup_insert($s
  *  The type of output being prepared. Possible values are:
  *    - 'list': The hardcoded admin lists of signups, eg at node/X/signups/admin
  *    - 'view': The form data field in Views.
- *    - 'mail': Email output. This is likely the only one that needs special 
+ *    - 'mail': Email output. This is likely the only one that needs special
  *      handling; in this case, modules should be more generous about supplying
  *      data since there's no other place to see it.
  */
 function signup_webform_signup_form_data_display_alter(&$form_data, $nid, $sid, $uid, $type = 'list') {
   //dsm($form_data);
-  // Cache any webform components we load, as we are probably coming here 
+  // Cache any webform components we load, as we are probably coming here
   // multiple times to show a set of signups that all involve the same webform.
   static $components = array();
   static $webform_loaded;
@@ -275,14 +665,21 @@ function signup_webform_signup_form_data
   foreach (_signup_webform_pane_ids($form_data) as $pane_id) {
     // Load the webform API.
     if (!isset($webform_loaded)) {
-      module_load_include('inc', 'webform', 'webform_submissions');
-      module_load_include('inc', 'webform', 'webform_components');
-      webform_load_components();
+      if (signup_webform_webform3()) {
+          module_load_include('inc', 'webform', 'includes/webform.submissions');
+          module_load_include('inc', 'webform', 'includes/webform.components');
+          webform_components();
+      }
+      else {
+          module_load_include('inc', 'webform', 'webform_submissions');
+          module_load_include('inc', 'webform', 'webform_components');
+          webform_load_components();
+      }
       $webform_loaded = TRUE;
     }
-    
+
     // Get the real nid from the prefixed pane ID.
-    $webform_nid = substr($pane_id, 8);
+    $webform_nid = drupal_substr($pane_id, 8);
 
     // Get the submission ID from the signup data and thence the submission.
     // We could get this from {signup_webform_submission}, but might as well
@@ -292,7 +689,16 @@ function signup_webform_signup_form_data
     // as an additional field for the ['signup_log']['form_data'] field.
     $submission_sid = $form_data[$pane_id]['sid'];
     $submission = webform_get_submission($webform_nid, $submission_sid);
-    
+
+    if (signup_webform_webform3()) {
+        /*
+        //-----------------------------------------
+        webform_client_form_pages($form, &$form_state);
+        webform_client_form_submit($form, &$form_state);
+        //-----------------------------------------
+        */
+    }
+    else {
     // Check there is an actual submission: if no webform fields are compulsory,
     // a user can sign up and not create a corresponding webform submission.
     if (isset($submission)) {
@@ -306,16 +712,16 @@ function signup_webform_signup_form_data
         $component = $components[$webform_nid][$cid];
         $label     = $components[$webform_nid][$cid]['name'];
         // Hijack webform's email output theming: this, as far as I can tell,
-        // is the only way there is of getting a component's data flattened to 
+        // is the only way there is of getting a component's data flattened to
         // a human-readable string.
         // @todo: textfields do not render properly here; I am assuming that
         // all single-values fields need their arrays exploding. Figure out
         // what is going on with webform and do this the correct way!
         if  (count($component_data['value']) == 1) {
-          $component_data['value'] = array_shift($component_data['value']); 
+          $component_data['value'] = array_shift($component_data['value']);
         }
         $themed_output = theme('webform_mail_' . $component['type'], $component_data['value'], $component);
-        // Use a numeric key rather than $label so the key is not output by 
+        // Use a numeric key rather than $label so the key is not output by
         // theme functions -- webform's output already includes the label.
         $form_data[$pane_id][] = $themed_output;
       }
@@ -323,6 +729,7 @@ function signup_webform_signup_form_data
     // Remove the sid from display: it is internal data.
     unset($form_data[$pane_id]['sid']);
   }
+  }
 }
 
 /**
@@ -332,23 +739,28 @@ function signup_webform_signup_form_data
  */
 function signup_webform_signup_cancel($signup, $node) {
   $form_data = unserialize($signup->form_data);
-  
+
   foreach (_signup_webform_pane_ids($form_data) as $pane_id) {
     // Load the webform API.
-    module_load_include('inc', 'webform', 'webform_submissions');
-    
+    if (signup_webform_webform3()) {
+        module_load_include('inc', 'webform', 'includes/webform.submissions');
+    }
+    else {
+        module_load_include('inc', 'webform', 'webform_submissions');
+    }
+
     // Get the real nid from the prefixed pane ID and thence the node.
-    $webform_nid = substr($pane_id, 8);
+    $webform_nid = drupal_substr($pane_id, 8);
     $webform_node = node_load($webform_nid);
-    
+
     // Get the submission ID from the signup data and thence the submission.
     $sid = $form_data[$pane_id]['sid'];
     $submission = webform_get_submission($webform_nid, $sid);
-    
+
     // Delete the webform submission.
     webform_submission_delete($webform_node, $submission);
     // Delete the signup-webform submission relationship.
-    db_query("DELETE FROM {signup_webform_submission} WHERE signup_sid = %d", $signup->sid);          
+    db_query("DELETE FROM {signup_webform_submission} WHERE signup_sid = %d", $signup->sid);
   }
 }
 
@@ -357,7 +769,7 @@ function signup_webform_signup_cancel($s
  *
  * When a whole signup node is deleted, delete data related to it.
  */
-/* 
+/*
 // needs work.
 function signup_webform_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
   if ($op == 'delete' && isset($node->signup_form_panes)) {
@@ -365,20 +777,25 @@ function signup_webform_nodeapi(&$node, 
     // Act on records pertaining to each webform that this signup is linked to.
     foreach (_signup_webform_pane_ids($node->signup_form_panes) as $pane_id) {
       // Load the webform API.
-      module_load_include('inc', 'webform', 'webform_submissions');
-      
-      $webform_nid = substr($pane_id, 8);
+      if (signup_webform_webform3()) {
+          module_load_include('inc', 'webform', 'includes/webform.submissions');
+      }
+      else {
+          module_load_include('inc', 'webform', 'webform_submissions');
+      }
+
+      $webform_nid = drupal_substr($pane_id, 8);
       $webform_node = node_load($webform_nid);
-      
-      // One webform may be used in several signup nodes. So we need to get 
+
+      // One webform may be used in several signup nodes. So we need to get
       // *only* the webform submissions that came from the signup node being deleted.
       // @todo BUG!!! this doesn't seem to work at all!
-      // do we even have {signup_log} any more at this point?? 
+      // do we even have {signup_log} any more at this point??
       // may be module weight issues here -- urgh!
       $result = db_query('SELECT sws.submission_sid FROM {signup_log} sl INNER JOIN {signup_webform_submission} sws ON sl.sid = sws.signup_sid WHERE sl.nid = %d', $signup_nid);
       // Act on each submission.
       while ($submission_data = db_fetch_array($result)) {
-        // Load the submission in order to delete it... 
+        // Load the submission in order to delete it...
         $submission = webform_get_submission($webform_nid, $submission_data['sid']);
         webform_submission_delete($webform_node, $submission);
         // Delete the signup-submission link for this submission.
@@ -389,7 +806,7 @@ function signup_webform_nodeapi(&$node, 
     }
   }
 }
-*/
+ */
 
 /**
  * Implementation of hook_form_FORM_ID_alter().
@@ -403,9 +820,9 @@ function signup_webform_form_node_delete
     $webform_nid = $node->nid;
     $pane_id = 'webform_' . $node->nid;
     // Get the signup nodes the pane based on this webform is used in.
-    // A left join gets us the special case where nid is 0 which represents the 
+    // A left join gets us the special case where nid is 0 which represents the
     // signup defaults.
-    $result = db_query("SELECT n.nid, n.title FROM {signup_panes} sp LEFT JOIN {node} n ON sp.nid = n.nid WHERE sp.pane_id = '%s'", $pane_id);
+    $result = db_query(db_rewrite_sql("SELECT n.nid, n.title FROM {signup_panes} sp LEFT JOIN {node} n ON sp.nid = n.nid WHERE sp.pane_id = '%s'"), $pane_id);
     while ($signup_node = db_fetch_object($result)) {
       if ($signup_node->nid == 0 ) {
         $text = t('Signup default settings');
@@ -426,10 +843,55 @@ function signup_webform_form_node_delete
 }
 
 /**
+ * Implementation of hook_form_FORM_ID_alter().
+ *
+ * If a webform submission that is also part of a signup_webform is being deleted
+ * prevent deletion.
+ */
+
+function signup_webform_form_webform_submission_delete_form_alter(&$form, &$form_state) {
+  $submission_sid = $form['details']['sid']['#value'];
+  if (db_result(db_query('SELECT COUNT(*) FROM {signup_webform_submission} WHERE submission_sid = %d', $submission_sid)) > 0) {
+    $result = db_query(db_rewrite_sql("SELECT sl.nid, n.title FROM {signup_log} sl INNER JOIN {signup_webform_submission} sws ON sl.sid = sws.signup_sid INNER JOIN {node} n ON sl.nid = n.nid WHERE sws.submission_sid = '%d'"), $submission_sid);
+    while ($signup_node = db_fetch_object($result)) {
+      $items[] = l($signup_node->title, 'node/' . $signup_node->nid);
+    }
+    $form['description']['#value'] = t('This webform submission can not be deleted because it is currently used in the signup-enabled content listed below:');
+    $form['description']['#suffix'] = theme('item_list', $items);
+    drupal_set_title(t('Unable to delete Submission #' . $submission_sid, array('%title' => $node->title)));
+    unset($form['actions']['submit']);
+  }
+}
+
+/**
+ * Form validation function.
+ */
+function signup_webform_form_validate($element, &$form_state) {
+  if (signup_webform_webform3()) {
+    foreach ($element as $element_id => $element_data) {
+      $this_webform_name = '';
+      $exploded_name = explode('_', $element_id);
+      if ($exploded_name[0] == 'webform') {
+        $webform_node = $element_data['#node'];
+        if ($webform_node->webform['submit_limit'] != -1) { // -1: Submissions are never throttled.
+          module_load_include('inc', 'webform', 'includes/webform.submissions');
+          if ($limit_exceeded = _webform_submission_limit_check($webform_node)) { // Check if submission limit has been reached.
+            $error = theme('webform_view_messages', $webform_node, 0, 1, 0, $limit_exceeded, array_keys(user_roles()));
+            form_set_error('', check_plain($error));
+            return;
+          }
+        }
+        _webform_client_form_validate($element_data, $form_state); // Validate
+      }
+    }
+  }
+}
+
+/**
  * Get the webform submission record for a given signup record.
  *
  * @param $signup
- *  The signup record object, as generally swilled around the place. 
+ *  The signup record object, as generally swilled around the place.
  * @param $webform_nid
  *  The node ID of the webform node in question.
  * @return
@@ -439,16 +901,28 @@ function signup_webform_get_signup_submi
   // Beware: both pieces of data we care about here are called sid!
   $submission_sid = db_result(db_query('SELECT submission_sid FROM {signup_webform_submission} WHERE signup_sid = %d AND webform_nid = %d', $signup->sid, $webform_nid));
   // Load the webform API.
-  module_load_include('inc', 'webform', 'webform_submissions');
-  $submission = webform_get_submission($webform_nid, $submission_sid);
+  if (signup_webform_webform3()) {
+      module_load_include('inc', 'webform', 'includes/webform.submissions');
+      /**
+      * Errors are suppressed here because webform_get_submission() throws a SQL warning for previously signed up users
+      * of an existing signup if a new webform has just been added that didn't exist when they initially registered.
+      * Once the signup is re-saved thus including the new webform, the warning will no longer appear.
+      */
+      $submission = @webform_get_submission($webform_nid, $submission_sid, TRUE);
+      }
+      else {
+      module_load_include('inc', 'webform', 'webform_submissions');
+      $submission = webform_get_submission($webform_nid, $submission_sid);
+  }
+
   return $submission;
 }
 
 /**
  * Helper function to make a lookup array of form keys => cid.
- * 
+ *
  * @param $webform_node
- *  Just feed this the entire webform $node object. 
+ *  Just feed this the entire webform $node object.
  */
 function _signup_webform_translate_cid_form_keys($webform_node) {
   $components = $webform_node->webform['components'];
@@ -460,7 +934,7 @@ function _signup_webform_translate_cid_f
 
 /**
  * Helper function to get the webform panes from an array on pane IDs.
- * 
+ *
  * Same pattern as element_children().
  *
  * @param $signup_data
@@ -470,8 +944,8 @@ function _signup_webform_translate_cid_f
  */
 function _signup_webform_pane_ids($signup_data) {
   $return = array();
-  foreach($signup_data as $pane_id => $data) {
-    if (substr($pane_id, 0, 7) == 'webform') {
+  foreach ($signup_data as $pane_id => $data) {
+    if (drupal_substr($pane_id, 0, 7) == 'webform') {
       $return[] = $pane_id;
     }
   }
