<?php

/**
 * This file contains the code used by the generated form pages.
 */

// ------------------------------------------------------------------------------------------------

/**
 * Called by forms generated by the Form Builder.
 *
 * @param array $config the published form configuration (result of calling fb_get_form_configuration())
 *              plus a couple of extra override vars for error purposes (error_code, validation_error).
 * @param integer $page an integer representing the page in the form: 1 to n (where n <= 8)
 * @param integer $submission_id this doesn't have to be passed for when the form is offline.
 */
function fb_generate_form_page($config, $page = 1, $submission_id = "")
{
	$published_form_id = $config["published_form_id"];

	// convert the placeholders into a placeholder_id => value hash
  $placeholders = array();
  foreach ($config["placeholders"] as $info)
  {
    $placeholders[$info["placeholder_id"]] = $info["placeholder_value"];
  }

	$settings = array(
	  "mode"                       => "live",
	  "published_form_id"          => $published_form_id,
	  "form_id"                    => $config["form_id"],
	  "view_id"                    => $config["view_id"],
	  "submission_id"              => $submission_id,
	  "template_set_id"            => $config["set_id"],
	  "page"                       => $page,
	  "include_review_page"        => ($config["include_review_page"] == "yes") ? true : false,
	  "include_thanks_page_in_nav" => ($config["include_thanks_page_in_nav"] == "yes") ? true : false,
    "is_online"                  => ($config["is_online"] == "yes") ? true : false,
    "thankyou_page_content"      => $config["thankyou_page_content"],
    "form_offline_page_content"  => $config["form_offline_page_content"],
	  "review_page_title"          => $config["review_page_title"],
	  "thankyou_page_title"        => $config["thankyou_page_title"],
	  "placeholders"               => $placeholders,

	  // special override vars
    "error_code"                 => isset($config["error_code"]) ? $config["error_code"] : "",
	  "validation_error"           => isset($config["validation_error"]) ? $config["validation_error"] : ""
	);

	// add in the templates
	foreach ($config["templates"] as $template_info)
	{
    $template_type = $template_info["template_type"];
    $settings["{$template_type}_template_id"] = $template_info["template_id"];
	}

	echo fb_generate_form($settings);
}


/**
 * Our top-level generation function. This generates the page from the appropriate template set and returns
 * every page in the form. Its used in the form builder section - it allows you to pass in particular values on the fly
 * to override what's actually stored in the database for the form configuration.
 *
 * Assumptions:
 * - the template set and templates within it have been validated for (a) all containing the required templates /
 *   placeholders and (b) the template set it complete.
 *
 * @param array $settings a hash containing the following info:
 *    Required:
 *      "form_id"
 *      "view_id"
 *      "set_id" => the template set to use
 *      "page"   => a particular page in the form (1-X, where X=the thankyou page)
 *
 *      - specific template IDs -
 *      "page_layout_template_id"
 *      "header_template_id"
 *      "footer_template_id"
 *      "navigation_template_id"
 *      "continue_block_template_id"
 *      "form_page_template_id"
 *      "review_page_template_id"
 *      "thankyou_page_template_id"
 *      "error_message_template_id"
 *
 *    Optional:
 *      "submission_id"    => if this is being used to generate the actual form, this will contain a value (unless the
 *                            form is offline)
 *      "placeholders"     => an array of IDs
 *      "error_code"       => for serious errors
 *      "validation_error" => when the page just failed server side validation, this contains the error message.
 *
 * @return array an indexed array of page content. If there's only a single tab in the View, the array will only contain
 *    a single index.
 */
function fb_generate_form($settings)
{
	global $g_root_dir, $g_root_url, $g_smarty_use_sub_dirs, $g_smarty;

	$mode    = $settings["mode"]; // preview / live
  $form_id = $settings["form_id"];
  $view_id = $settings["view_id"];
  $published_form_id          = isset($settings["published_form_id"]) ? $settings["published_form_id"] : "";
  $template_set_id            = $settings["template_set_id"];
  $include_review_page        = $settings["include_review_page"];
  $include_thanks_page_in_nav = $settings["include_thanks_page_in_nav"];

  $templates = array(
    "page_layout"    => fb_get_template($settings["page_layout_template_id"]),
    "header"         => fb_get_template($settings["header_template_id"]),
    "footer"         => fb_get_template($settings["footer_template_id"]),
    "navigation"     => fb_get_template($settings["navigation_template_id"]),
    "continue_block" => fb_get_template($settings["continue_block_template_id"]),
    "error_message"  => fb_get_template($settings["error_message_template_id"])
  );

  $form_info = ft_get_form($form_id);
  $view_info = ft_get_view($view_id);

  // a little helper function to make sense of the awful crap returned by ft_get_view
  $view_tabs = fb_get_view_tabs_from_view_info($view_info);

  // now figure out what page type we're dealing with. We figure this out by looking at the $settings["page"]
  // value, which contains a numeric value 1-8
  $current_page = $settings["page"];

  if (isset($settings["error_code"]) && !empty($settings["error_code"]))
  {
  	$templates["page"] = array(
  	  "content"   => "<div>Error: <span class=\"fb_error_code\">{$settings["error_code"]}</span></div>",
  	  "page_type" => "error"
  	);

    $current_page = 1;
  }

  else if (!$settings["is_online"])
  {
    $templates["page"] = fb_get_template($settings["form_offline_page_template_id"]);
    $current_page = 1;
  }

  else
  {
  	$page_type = fb_get_current_page_type($current_page, $view_tabs, $include_review_page);

  	switch ($page_type)
  	{
  		case "form_page":
  			$templates["page"] = fb_get_template($settings["form_page_template_id"]);
  			break;
  		case "review_page":
  			$templates["page"] = fb_get_template($settings["review_page_template_id"]);
  			break;
  		case "thanks_page":
  			$templates["page"] = fb_get_template($settings["thankyou_page_template_id"]);
  			break;
  	}
  }

  // construct the list of pages that should appear in the navigation.
	$params = array(
	  "view_tabs"                  => $view_tabs,
	  "include_review_page"        => $include_review_page,
	  "include_thanks_page_in_nav" => $include_thanks_page_in_nav,
    "review_page_title"          => $settings["review_page_title"],
    "thankyou_page_title"        => $settings["thankyou_page_title"]
	);
	$nav_pages = fb_get_nav_pages($params);

  $smarty = fb_create_new_smarty_instance();
  $smarty->assign("mode", $mode);
  $smarty->assign("template_set_id", $template_set_id);
  $smarty->assign("namespace", "form_builder_{$published_form_id}");
  $smarty->assign("published_form_id", $published_form_id);
  $smarty->assign("review_page_title", $settings["review_page_title"]);
  $smarty->assign("include_review_page", $include_review_page);
  $smarty->assign("include_thanks_page_in_nav", $include_thanks_page_in_nav);
  $smarty->assign("nav_pages", $nav_pages);
  $smarty->assign("templates", $templates);
  $smarty->assign("form_name", $form_info["form_name"]);
  $smarty->assign("form_id", $form_id);
  $smarty->assign("view_name", $view_info["view_name"]);
  $smarty->assign("view_id", $view_id);
  $smarty->assign("view_info", $view_info);
  $smarty->assign("num_form_pages", count($view_tabs));
  $smarty->assign("page_titles", $view_tabs);
  $smarty->assign("g_root_url", $g_root_url);
  $smarty->assign("g_root_dir", $g_root_dir);
  $smarty->assign("thankyou_page_content", $settings["thankyou_page_content"]);
  $smarty->assign("form_offline_page_content", $settings["form_offline_page_content"]);

  if (isset($settings["submission_id"]) && !empty($settings["submission_id"]))
    $smarty->assign("submission_id", $settings["submission_id"]);


  // TODO, only include codemirror if needed. It's a fringe case.
  $required_resources =<<< END
  <script>
  //<![CDATA[
  var g = {
    root_url:       "$g_root_url",
    error_colours:  ["ffbfbf", "ffb5b5"],
    notify_colours: ["c6e2ff", "97c7ff"]
  };
  //]]>
  </script>
  <script src="$g_root_url/global/scripts/jquery.js"></script>
  <link href="$g_root_url/themes/default/css/smoothness/jquery-ui-1.8.6.custom.css" rel="stylesheet" type="text/css"/>
  <script src="$g_root_url/themes/default/scripts/jquery-ui-1.8.6.custom.min.js"></script>
  <script src="$g_root_url/global/scripts/general.js"></script>
  <script src="$g_root_url/global/scripts/rsv.js"></script>
  <script src="$g_root_url/global/scripts/field_types.php"></script>
  <link rel="stylesheet" href="$g_root_url/global/css/field_types.php" type="text/css" />
	<script src="$g_root_url/global/codemirror/js/codemirror.js"></script>
	<script src="$g_root_url/global/scripts/jquery-ui-timepicker-addon.js"></script>
	<script src="$g_root_url/global/fancybox/jquery.fancybox-1.3.4.pack.js"></script>
	<link rel="stylesheet" href="$g_root_url/global/fancybox/jquery.fancybox-1.3.4.css" type="text/css" media="screen" />
END;

  // shame, but we need to use buffering to capture the standalone hook outputs. Otherwise, we'd need
  // users to add the template hooks directly in their templates, which would be confusing
  ob_start();
  ft_process_template_hook_calls("standalone_form_fields_head_top", $smarty->_tpl_vars, array());
  $standalone_head_top = ob_get_contents();
  ob_end_clean();

  ob_start();
  ft_process_template_hook_calls("standalone_form_fields_head_bottom", $smarty->_tpl_vars, array());
  $standalone_head_bottom = ob_get_contents();
  ob_end_clean();

  $required_resources = $standalone_head_top . $required_resources . $standalone_head_bottom;
  $smarty->assign("required_resources", $required_resources);

  // add the template set resources
  $resources = fb_get_resources($template_set_id);
  $resource_placeholders = array();

  // TODO to prevent caching in "real" browsers
  $now = date("U");

  // used when editing in the Form Builder. Placeholders info needs to be passed to the css.php generation file
  $query_str = "";
  if ($mode == "preview")
  {
  	$query_str = "&source=sessions";
  }
  else
  {
  	$query_str = "&published_form_id={$settings["published_form_id"]}";
  }

  foreach ($resources as $resource_info)
  {
  	$resource_id = $resource_info["resource_id"];
  	$placeholder = $resource_info["placeholder"];
    $link = "<link type=\"text/css\" rel=\"stylesheet\" href=\"$g_root_url/modules/form_builder/global/form_resources/css.php?resource_id=$resource_id&nocache=$now{$query_str}\">";
    $resource_placeholders[$placeholder] = $link;
  }
  $smarty->assign("R", $resource_placeholders);

  // add the Template Set placeholders
  $placeholders = fb_get_placeholders($template_set_id);
  $P = array();
  foreach ($placeholders as $placeholder_info)
  {
  	$placeholder_id = $placeholder_info["placeholder_id"];
  	$placeholder    = $placeholder_info["placeholder"];

  	// this shouldn't ever occur
  	if (!array_key_exists($placeholder_id, $settings["placeholders"]))
  	  continue;

    // TODO multi-select + checkboxes...
    $P[$placeholder] = (isset($settings["placeholders"][$placeholder_id])) ? $settings["placeholders"][$placeholder_id] : "";
  }
  $smarty->assign("P", $P);


  // if there's a validation error, add that too
  if (isset($settings["validation_error"]) && !empty($settings["validation_error"]))
    $smarty->assign("validation_error", $settings["validation_error"]);

  // now generate the page content
  $smarty->assign("num_pages", count($nav_pages));
  $smarty->assign("current_page", $current_page);
  $smarty->assign("eval_str", $templates["page_layout"]["content"]);
  $page_content = $smarty->fetch("../../modules/form_builder/smarty/eval.tpl");

  return $page_content;
}


/**
 * Processes a form submission from a Form Builder page. This is actually a simplified version of the ft_api_process_form_page()
 * function, with all unnecessary code removed. Since we're controlling the actual form creation, much of the code is no longer
 * necessary.
 *
 * @param array $params
 *
 *     Required keys:
 *        "submit_button": the "name" attribute value of the form submit button
 *        "form_data": the contents of $_POST (or $_GET, if "method" setting is set to "GET" ... )
 *        "file_data": the contents of $_FILES (only needed if your form contained file fields)
 *        "next_page": the URL (relative or absolute) of which page to redirect to (e.g. the next page
 *               in the form or the "thankyou" page).
 *        "finalize": this tells the function to finalize the submission. This prevents it being subsequently
 *               editable via this function and makes the submission appear in the Form Tools UI.
 *        "no_sessions_url": for multi-page forms it's a good idea to pass along this value. It should be the URL
 *               of a page (usually the FIRST page in the form sequence) where the user will be redirected to if
 *               they didn't start the form from the first page. It ensures the form submission gets created &
 *               submitted properly.
 *        "namespace": if you specified a custom namespace for ft_api_init_form_page, for where the form values will
 *               be stored temporarily in sessions, you need to pass that same value to this function - otherwise
 *               it won't be able to retrieve the form and submission ID
 *        "send_emails": (boolean). By default, Form Tools will trigger any emails that have been attached to the
 *               "on submission" event ONLY when the submission is finalized (finalize=true). This setting provides
 *               you with direct control over when the emails get sent. If not specified, will use the default
 *               behaviour.
 *
 * @return mixed ordinarily, this function will just redirect the user to whatever URL is specified in the
 *        "next_page" key. But if that value isn't set, it returns an array:
 *               [0] success / false
 *               [1] if failure, the API Error Code, otherwise blank
 */
function fb_process_form_builder_page($params)
{
  global $g_table_prefix, $g_root_url, $g_multi_val_delimiter, $LANG, $g_api_recaptcha_private_key;

  if (!isset($params["form_data"][$params["submit_button"]]))
    return;

  $namespace          = $params["namespace"];
  $submission_id      = $params["submission_id"];
  $config             = $params["config"];
  $page               = $params["page"];
  $page_type          = $params["page_type"];
  $form_id            = $params["form_id"];
  $view_id            = $params["view_id"];
  $form_data          = $params["form_data"];
  $no_sessions_url    = $params["no_sessions_url"];
  $submit_button_name = $params["submit_button"];
  $next_page          = $params["next_page"];
  $file_data          = $params["file_data"];
  $finalize           = isset($params["finalize"]) ? $params["finalize"] : false;

  $form_info = ft_get_form($form_id);

  $failed_validation = false;
  $validation_error = "";
  $update_successful = "";
  if ($page_type == "form")
  {
    $tabs = ft_get_view_tabs($view_id, true);
    $curr_page = $page;
    if (empty($tabs))
      $curr_page = "";

	  $view_fields = ft_get_grouped_view_fields($view_id, $curr_page);

	  $field_ids = array();
	  $editable_field_ids = array();
	  foreach ($view_fields as $view_field_group)
	  {
	  	foreach ($view_field_group["fields"] as $field_info)
	  	{
	  		$field_id = $field_info["field_id"];
	  	  $field_ids[] = $field_id;
	  	  if ($field_info["is_editable"] == "yes")
	  	    $editable_field_ids[] = $field_id;
	  	}
	  }

	  $form_data["view_id"] = $view_id;

	  // this is awful. It's a problem with the Core, not so much this module.
	  $form_data["field_ids"] = implode(",", $field_ids); // *sigh*
	  $form_data["editable_field_ids"] = $editable_field_ids;

	  list($update_successful, $validation_error) = ft_update_submission($form_id, $submission_id, $form_data);

    // if there was any problem udpating this submission, make a special note of it: we'll use that info to merge the current POST request
    // info with the original field values to ensure the page contains the latest data (i.e. for cases where they fail server-side validation)
    if (!$update_successful)
    {
      $failed_validation = true;
    }
  }

  // the reCAPTCHA can be placed on the form or review page (only!)
  $has_captcha = isset($form_data["recaptcha_response_field"]) ? true : false;
  if ($has_captcha && ($page_type == "form" || $page_type == "review"))
  {
    // was there a reCAPTCHA response? If so, a recaptcha was just submitted, check it was entered correctly
    $passes_captcha = true;
    if ($has_captcha)
    {
      $passes_captcha = false;
      $recaptcha_challenge_field = $form_data["recaptcha_challenge_field"];
      $recaptcha_response_field  = $form_data["recaptcha_response_field"];

      require_once(realpath(dirname(__FILE__) . "/../../../../global/api/recaptchalib.php"));
      $resp = recaptcha_check_answer($g_api_recaptcha_private_key, $_SERVER["REMOTE_ADDR"], $recaptcha_challenge_field, $recaptcha_response_field);

      if ($resp->is_valid)
      {
        // keep track of the fact that the user has entered the CAPTCHA properly so they aren't shown the captcha again
      	$passes_captcha = true;
        $_SESSION[$namespace]["passed_captcha"] = true;
      }
      else
      {
      	// if the main update was successful, but they failed validation, just display the single "wrong captcha" error
      	if ($update_successful)
      	{
      	  $validation_error = "&bull;&nbsp; Sorry, you didn't enter the reCAPTCHA correctly. Please try again.";
      	}
      	else
      	{
          $br = (!empty($validation_error)) ? "<br />" : "";
      		$validation_error .= $br . "&bull;&nbsp; Sorry, you didn't enter the reCAPTCHA correctly. Please try again.";
      	}

        $failed_validation = true;
      }
    }
  }

  if (!$failed_validation)
  {
	  // this automatically sends any emails set to the on_submission trigger.
	  if ($finalize)
	  {
	  	ft_finalize_submission($form_id, $submission_id);
	  }

	  if (!empty($next_page))
	  {
	  	if (!in_array($page, $_SESSION[$namespace]["form_tools_completed_pages"]))
	  	{
	  	  $_SESSION[$namespace]["form_tools_completed_pages"][] = $page;
	  	}
	    header("location: $next_page");
	    exit;
	  }
  }

  return array(false, $validation_error);
}


/**
 * Initializes a Form Builder page. If the sessions are being newly created (i.e. they just arrived at the form)
 * the first return array index contains true. False otherwise.
 *
 * @param integer $form_id
 * @param integer $view_id
 * @param string $namespace
 * @return array [0] whether the sessions were just created or not
 *               [1] the current form data
 */
function fb_init_form_builder_page($form_id, $view_id, $namespace)
{
  global $g_session_type, $g_session_save_path;

  $header_charset = "UTF-8";

  $newly_created = false;
  if (!isset($_SESSION[$namespace]) || empty($_SESSION[$namespace]))
  {
  	$newly_created = true;
    $_SESSION[$namespace] = array();
    $submission_id = ft_create_blank_submission($form_id, $view_id, false);

    $_SESSION[$namespace]["form_tools_form_id"]         = $form_id;
    $_SESSION[$namespace]["form_tools_view_id"]         = $view_id;
    $_SESSION[$namespace]["form_tools_submission_id"]   = $submission_id;
    $_SESSION[$namespace]["form_tools_completed_pages"] = array();
  }

  return array($newly_created, $_SESSION[$namespace]);
}



/**
 * Clears sessions after successfully completing a form.
 *
 * @param string $namespace (optional);
 */
function fb_clear_form_builder_form_sessions($namespace)
{
  $_SESSION[$namespace] = "";
  unset($_SESSION[$namespace]);
}


/**
 * This is called on every published form. It checks that the form ID, View ID and all the template IDs
 * actually exist.
 *
 * @param array $config
 */
function fb_check_live_form_conditions($config)
{
	global $g_table_prefix;

  if (!isset($config["form_id"]) || !ft_check_form_exists($config["form_id"]))
  {
  	return array("success" => false, "error_code" => "FB100");
  }
  if (!isset($config["view_id"]) || !ft_check_view_exists($config["view_id"]))
  {
  	return array("success" => false, "error_code" => "FB101");
  }

  // check all the templates exist. Just do a count.
  $template_ids = array();
  foreach ($config["templates"] as $template_info)
  {
  	$template_ids[] = $template_info["template_id"];
  }
  $num_templates = count($template_ids);
  $template_id_str = implode(",", $template_ids);
  $query = mysql_query("SELECT count(*) as c FROM {$g_table_prefix}module_form_builder_templates WHERE template_id IN ($template_id_str)");
  $result = mysql_fetch_assoc($query);

  if ($num_templates != $result["c"])
  {
  	return array("success" => false, "error_code" => "FB102");
  }

  return "";
}


/**
 * Called on every published form page. This checks that the current page number being passed via the query
 * string is valid. It checks that (a) it wasn't hacked to contain any non-numeric content, (b) it's within
 * the range of pages in this form configuration and (c) they aren't skipping any pages: each page has
 * to be submitted in sequence.
 *
 * @param integer $page
 * @param array $pages
 */
function fb_verify_page_number($page, $pages, $namespace)
{
	$num_pages = count($pages);
  if (!is_numeric($page) || $page < 1)
  {
    $page = 1;
  }
  else if ($page > $num_pages)
  {
  	$page = $num_pages;
  }

  // now look to see what pages the user has already filled in
  $completed_pages = (isset($_SESSION[$namespace]["form_tools_completed_pages"])) ? $_SESSION[$namespace]["form_tools_completed_pages"] : array();

  // if the previous page isn't marked as complete, set the page to the highest completed page + 1
  if ($page != 1 && !in_array($page-1, $completed_pages))
  {
  	if (!empty($completed_pages))
  	{
      $page = max($completed_pages) + 1;
  	}
    else
      $page = 1;
  }

	return $page;
}


/**
 * Called on every published form page. This handles the scenario where the form is no longer online, either via the schedule
 * or by the user explicitly setting the published form to offline.
 *
 * @param array $config
 * @param string $namespace
 */
function fb_check_form_offline($config, $namespace)
{
	$module_settings = ft_get_module_settings("", "form_builder");
	$just_taken_offline = fb_take_scheduled_form_offline($config);

  // if the form is marked as offline
	if ($config["is_online"] == "no")
	{
		// the user doesn't already have any sessions created (i.e. they weren't in the midst of submitting the
		// form!), we just display the Form Offline page
		if (!isset($_SESSION[$namespace]["form_tools_submission_id"]))
		{
			fb_clear_form_builder_form_sessions($namespace);
	    fb_generate_form_page($config, 1);
		  exit;
		}
		else
		{
			// here we have a special fringe case: the form just went offline but the user already started putting
			// through the form. How we handle THAT, depends on what they choose for the "Offline form behaviour" setting
			if ($module_settings["scheduled_offline_form_behaviour"] == "cutoff")
			{
				fb_clear_form_builder_form_sessions($namespace);
	      fb_generate_form_page($config, 1);
		    exit;
			}
			else
			{
				// do nothing! For this scenario, we just allow them to proceed (i.e. let the function return nothing). As soon
				// as they complete their form, sessions will be emptied and they won't be able to put through another
			}
		}
	}

	return true;
}


/**
 * This blithely checks a published form to figure out if it needs to be taken offline. This is called for every published
 * form on each page load, and on the Publish Tab in the admin section.
 *
 * @param array $config
 * @return boolean whether or not the form was just taken offline
 */
function fb_take_scheduled_form_offline($config)
{
	global $g_table_prefix;

	$just_taken_offline = false;

	// first, check the form shouldn't be taken offline right now
	if ($config["is_online"] == "yes" && $config["offline_date"] != "0000-00-00 00:00:00")
	{
    $default_timezone_offset = ft_get_settings("default_timezone_offset");

    $now = date("U");
		$now = $now + ($default_timezone_offset * 60 * 60);

		$offline_unixtime = ft_convert_datetime_to_timestamp($config["offline_date"]);

		// is the offline datetime just passed, take the sucker offline
    if ($now > $offline_unixtime)
    {
    	$published_form_id = $config["published_form_id"];
      mysql_query("
        UPDATE {$g_table_prefix}module_form_builder_forms
        SET    is_online = 'no',
               offline_date = '0000-00-00 00:00:00'
        WHERE  published_form_id = $published_form_id
      ");
      $just_taken_offline = true;
    }
	}

	return $just_taken_offline;
}


function fb_init_sessions()
{
	global $g_session_type, $g_session_save_path, $g_api_header_charset;

	$header_charset = "utf-8";
	if (isset($g_api_header_charset) && !empty($g_api_header_charset))
    $header_charset = $g_api_header_charset;

  if (!isset($_SESSION))
  {
    if ($g_session_type == "database")
      $sess = new SessionManager();

    if (!empty($g_session_save_path))
      session_save_path($g_session_save_path);

    session_start();
    header("Cache-control: private");
    header("Content-Type: text/html; charset=$header_charset");
  }
}


/**
 * Deletes all unfinalized submissions and any associated files that have been uploaded. For safety,
 * it only deletes incomplete submissions that are 24 hours old.
 *
 * @return integer the number of unfinalized submissions that were just deleted, or false if it failed.
 */
function fb_delete_unfinalized_submissions($form_id)
{
  global $g_table_prefix;

  if (!ft_check_form_exists($form_id))
    return false;

  $query = mysql_query("
    SELECT *
    FROM   {$g_table_prefix}form_{$form_id}
    WHERE  is_finalized = 'no' AND
    DATE_ADD(submission_date, INTERVAL 24 HOUR) < curdate()
      ");

  if (mysql_num_rows($query) == 0)
    return 0;

  // find out which of this form are file fields
  $form_fields = ft_get_form_fields($form_id, array("include_field_type_info" => true));

  $file_field_info = array(); // a hash of col_name => file upload dir
  foreach ($form_fields as $field_info)
  {
    if ($field_info["is_file_field"] == "file")
    {
      $field_id = $field_info["field_id"];
      $col_name = $field_info["col_name"];
      $extended_settings = ft_get_extended_field_settings($field_id);
      $file_field_info[$col_name] = $extended_settings["file_upload_dir"];
    }
  }

  // now delete the info
  while ($submission_info = mysql_fetch_assoc($query))
  {
    $submission_id = $submission_info["submission_id"];

    // delete any files associated with the submission
    while (list($col_name, $file_upload_dir) = each($file_field_info))
    {
      if (!empty($submission_info[$col_name]))
        @unlink("{$file_upload_dir}/{$submission_info[$col_name]}");
    }
    reset($file_field_info);

    mysql_query("DELETE FROM {$g_table_prefix}form_{$form_id} WHERE submission_id = $submission_id");
  }

  return mysql_num_rows($query);
}


/**
 * Used in the generated forms to figure out whether the submission needs to be finalized. Finalization is always done
 * on the penultimate step - right before redirecting to the thankyou page. Figuring out
 *
 * @param unknown_type $page
 * @param unknown_type $pages
 */
function fb_is_final_step($current_page, $pages)
{
	echo $page;
	print_r($pages);
	exit;
}