Revision: 2251
          http://mrbs.svn.sourceforge.net/mrbs/?rev=2251&view=rev
Author:   cimorrison
Date:     2012-01-23 14:35:01 +0000 (Mon, 23 Jan 2012)
Log Message:
-----------
Committing code before making some changes to edit_entry_handler.php.   All 
that happens at the moment is that areas and rooms are created if necessary, 
but no bookings are made.

Modified Paths:
--------------
    mrbs/branches/ics_import/web/add.php
    mrbs/branches/ics_import/web/functions.inc
    mrbs/branches/ics_import/web/functions_ical.inc
    mrbs/branches/ics_import/web/lang.en
    mrbs/branches/ics_import/web/mrbs_auth.inc
    mrbs/branches/ics_import/web/mrbs_sql.inc

Added Paths:
-----------
    mrbs/branches/ics_import/web/import.php

Modified: mrbs/branches/ics_import/web/add.php
===================================================================
--- mrbs/branches/ics_import/web/add.php        2012-01-19 13:50:50 UTC (rev 
2250)
+++ mrbs/branches/ics_import/web/add.php        2012-01-23 14:35:01 UTC (rev 
2251)
@@ -3,6 +3,7 @@
 // $Id$
 
 require_once "defaultincludes.inc";
+require_once "mrbs_sql.inc";
 
 // Get non-standard form variables
 $name = get_form_var('name', 'string');
@@ -15,6 +16,8 @@
 
 // This file is for adding new areas/rooms
 
+$error = '';
+
 // First of all check that we've got an area or room name
 if (!isset($name) || ($name === ''))
 {
@@ -25,105 +28,12 @@
 // or an area
 elseif ($type == "area")
 {
-  // Truncate the name field to the maximum length as a precaution.
-  $name = substr($name, 0, $maxlength['area.area_name']);
-  $area_name_q = addslashes($name);
-  // Acquire a mutex to lock out others who might be editing the area
-  if (!sql_mutex_lock("$tbl_area"))
-  {
-    fatal_error(TRUE, get_vocab("failed_to_acquire"));
-  }
-  // Check that the area name is unique
-  if (sql_query1("SELECT COUNT(*) FROM $tbl_area WHERE 
area_name='$area_name_q' LIMIT 1") > 0)
-  {
-    $error = "invalid_area_name";
-  }
-  // If so, insert the area into the database.   We insert the area name that
-  // we have been given, together with the default values for the per-area 
settings
-  else
-  {
-    // Build arrays of data to be inserted into the table
-    $sql_col = array();
-    $sql_val = array();
-    // Get the information about the fields in the room table
-    $fields = sql_field_info($tbl_area);
-    // Loop through the fields and build up the arrays
-    foreach ($fields as $field)
-    {
-      $key = $field['name'];
-      switch ($key)
-      {
-      case 'area_name':
-        $sql_col[] = $key;
-        $sql_val[] = "'$area_name_q'";
-        break;
-      default:
-        if (array_key_exists($key, $area_defaults))
-        {
-          $sql_col[] = $key;
-          if (in_array($key, $boolean_fields['area']))
-          {
-            $sql_val[] = ($area_defaults[$key]) ? 1 : 0;
-          }
-          elseif ($field['nature'] == 'integer')
-          {
-            $sql_val[] = $area_defaults[$key];
-          }
-          else
-          {
-            $sql_val[] = "'" . addslashes($area_defaults[$key]) . "'";
-          }
-        }
-        break;
-      }
-    }
-    $sql = "INSERT INTO $tbl_area (" . implode(', ',$sql_col) . ") VALUES (" . 
implode(', ',$sql_val) . ")";
-    if (sql_command($sql) < 0)
-    {
-      trigger_error(sql_error(), E_USER_WARNING);
-      fatal_error(TRUE, get_vocab("fatal_db_error"));
-    }
-    $area = sql_insert_id("$tbl_area", "id");
-  }
-  // Release the mutex
-  sql_mutex_unlock("$tbl_area");
+  $area = mrbsAddArea($name, $error);
 }
 
 elseif ($type == "room")
 {
-  // Truncate the name and description fields to the maximum length as a 
precaution.
-  $name = substr($name, 0, $maxlength['room.room_name']);
-  $description = substr($description, 0, $maxlength['room.description']);
-  // Add SQL escaping
-  $room_name_q = addslashes($name);
-  $description_q = addslashes($description);
-  if (empty($capacity))
-  {
-    $capacity = 0;
-  }
-  // Acquire a mutex to lock out others who might be editing rooms
-  if (!sql_mutex_lock("$tbl_room"))
-  {
-    fatal_error(TRUE, get_vocab("failed_to_acquire"));
-  }
-  // Check that the room name is unique within the area
-  if (sql_query1("SELECT COUNT(*) FROM $tbl_room WHERE 
room_name='$room_name_q' AND area_id=$area LIMIT 1") > 0)
-  {
-    $error = "invalid_room_name";
-  }
-  // If so, insert the room into the datrabase
-  else
-  {
-    $sql = "INSERT INTO $tbl_room (room_name, sort_key, area_id, description, 
capacity)
-            VALUES ('$room_name_q', '$room_name_q', $area, 
'$description_q',$capacity)";
-    if (sql_command($sql) < 0)
-    {
-      trigger_error(sql_error(), E_USER_WARNING);
-      fatal_error(TRUE, get_vocab("fatal_db_error"));
-    }
-  }
-  // Release the mutex
-  sql_mutex_unlock("$tbl_room");
+  $room = mrbsAddRoom($name, $area, $error, $description, $capacity);
 }
 
 $returl = "admin.php?area=$area" . (!empty($error) ? "&error=$error" : "");

Modified: mrbs/branches/ics_import/web/functions.inc
===================================================================
--- mrbs/branches/ics_import/web/functions.inc  2012-01-19 13:50:50 UTC (rev 
2250)
+++ mrbs/branches/ics_import/web/functions.inc  2012-01-23 14:35:01 UTC (rev 
2251)
@@ -48,6 +48,22 @@
   }
 }
 
+
+// Get the default timezone.  Caters for PHP servers that don't
+// have date_default_timezone_get()
+function mrbs_default_timezone_get()
+{
+  if (function_exists("date_default_timezone_get"))
+  {
+    return date_default_timezone_get();
+  }
+  else
+  {
+    return getenv('TZ');
+  }
+}
+
+
 // Deal with $private_xxxx overrides.  Simplifies
 // logic related to private bookings.
 global $private_override;

Modified: mrbs/branches/ics_import/web/functions_ical.inc
===================================================================
--- mrbs/branches/ics_import/web/functions_ical.inc     2012-01-19 13:50:50 UTC 
(rev 2250)
+++ mrbs/branches/ics_import/web/functions_ical.inc     2012-01-23 14:35:01 UTC 
(rev 2251)
@@ -8,6 +8,9 @@
 // and the calendar
 $vtimezone = get_vtimezone($timezone);
 
+// Create an array which can be used to map day of the week numbers (0..6)
+// onto days of the week as defined in RFC 5545
+$RFC_5545_days = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
 
 // Extracts a VTIMEZONE component from a VCALENDAR.
 function extract_vtimezone($vcalendar)
@@ -192,6 +195,236 @@
 }
 
 
+// Returns a UNIX timestamp given an RFC5545 date or date-time
+// $params is an optional second argument and is an array of property 
parameters
+function get_time($value)
+{
+  if (func_num_args() > 1)
+  {
+    $params = func_get_arg(1);
+  }
+  // If we haven't got any parameters default to "UTC".   Not strictly correct,
+  // but in most cases it will be true.  Need to do something better.
+  if (empty($params))
+  {
+    $this_timezone = "UTC";
+  }
+  
+  $value_type = "DATE_TIME";  // the default
+
+  
+  // Work out which, if any, parameters have been set
+  if (isset($params))
+  {
+    foreach ($params as $param_name => $param_value)
+    {
+      switch ($param_name)
+      {
+        case 'VALUE':
+          $value_type = $param_value;
+          break;
+        case 'TZID':
+          $this_timezone = $param_value;
+          break;
+      }
+    }
+  }
+  
+  if (strpos($value, 'Z') !== FALSE)
+  {
+    $value = str_replace('Z', '', $value);
+    $this_timezone = 'UTC';
+  }
+  if ($value_type == "DATE_TIME")
+  {
+    list($date, $time) = explode('T', $value, 2);
+  }
+  else
+  {
+    $date = $value;
+    $time = '000000';
+  }
+  $year = substr($date, 0, 4);
+  $month = substr($date, 4, 2);
+  $day = substr($date, 6, 2);
+  $hour = substr($time, 0, 2);
+  $minute = substr($time, 2, 2);
+  $second = substr($time, 4, 2);
+  if (isset($this_timezone))
+  {
+    if (strtoupper($this_timezone) == 'UTC')
+    {
+      $result = gmmktime($hour, $minute, $second, $month, $day, $year);
+    }
+    else
+    {
+      $old_timezone = mrbs_default_timezone_get();
+      mrbs_default_timezone_set($this_timezone);
+      $result = mktime($hour, $minute, $second, $month, $day, $year);
+      mrbs_default_timezone_set($old_timezone);
+    }
+  }
+  else
+  {
+    if ($value_type == "DATE_TIME")
+    {
+      trigger_error("Floating times not supported", E_USER_WARNING);
+    }
+    $result = mktime($hour, $minute, $second, $month, $day, $year);
+  }
+  return $result;
+}
+
+
+// Returns an MRBS rep_opt string given an array of RFC 5545 days
+function get_rep_opt($byday_days)
+{
+  global $RFC_5545_days;
+  
+  $rep_opt = '';
+  foreach ($RFC_5545_days as $day)
+  {
+    $rep_opt .= (in_array($day, $byday_days)) ? '1' : '0';
+  }
+  return $rep_opt;
+}
+
+
+// Given an RFC 5545 recurrence rule, returns an array giving the MRBS repeat
+// details.   Indexed by rep_type, rep_num_weeks, rep_opt, end_date
+function get_repeat_details($rrule, $start_time)
+{
+  global $RFC_5545_days;
+  
+  $result = array();
+  $rules = array();
+  $recur_rule_parts = explode(';', $rrule);
+  foreach ($recur_rule_parts as $recur_rule_part)
+  {
+    list($name, $value) = explode('=', $recur_rule_part);
+    $rules[$name] = $value;
+  }
+
+  if (!isset($rules['FREQ']))
+  {
+    trigger_error("Invalid RRULE: missing FREQ part");
+    return FALSE;
+  }
+  
+  switch ($rules['FREQ'])
+  {
+    case 'DAILY':
+      $result['rep_type'] = REP_DAILY;
+      break;
+    case 'WEEKLY':
+      if (isset($rules['interval']) && ($rules['interval'] > 1))
+      {
+        $result['rep_type'] = REP_N_WEEKLY;
+        $result['rep_num_weeks'] = $rules['interval'];
+      }
+      else
+      {
+        $result['rep_type'] = REP_WEEKLY;
+      }
+      if (isset($rules['BYDAY']))
+      {
+        $byday_days = explode(',', $rules['BYDAY']);
+      }
+      else
+      {
+        // If there's no repeat day specified in the RRULE then
+        // 'the day is gotten from "DTSTART"'
+        $byday_days = array($RFC_5545_days[date('w', $start_time)]);
+      }
+      $result['rep_opt'] = get_rep_opt($byday_days);
+      break;
+    case 'MONTHLY':
+      if (!isset($rules['BYDAY']))
+      {
+        $result['rep_type'] = REP_MONTHLY;
+      }
+      else
+      {
+        $result['rep_type'] = REP_MONTHLY_SAMEDAY;
+        $byday_days = explode(',', $rules['BYDAY']);
+        if (count($byday_days) > 1)
+        {
+          trigger_error("MRBS does not support more than one BYDAY value when 
FREQ=${result['freq']}");
+        }
+        foreach ($byday_days as $byday_day)
+        {
+          $day = substr($byday_day, -2);     // the last two characters of the 
string
+          $nth = substr($byday_day, 0, -2);  // everything except the last two 
characters
+          if ($nth === FALSE)
+          {
+            // "If an integer modifier is not present, it means all days of 
this
+            // type within the specified frequency.  For example, within a 
MONTHLY
+            // rule, MO represents all Mondays within the month." [RFC 5545]
+            // So that comes to the same thing as a WEEKLY repeat
+            $result['rep_type'] = REP_WEEKLY;
+            $result['rep_opt'] = get_rep_opt(array($day));
+          }
+          else
+          {
+            if ((int) $nth < 0)
+            {
+              trigger_error("MRBS does not support negative BYDAY values 
($nth$day)", E_USER_WARNING);
+              $unsupported_rules = TRUE;
+            }
+            elseif ($nth == '5')
+            {
+              trigger_error("MRBS does not support a BYDAY value of 5 
($nth$day)", E_USER_WARNING);
+              $unsupported_rules = TRUE;
+            }
+            // otherwise we're OK and we don't need to do anything more 
because we know
+            // we've only got one day and the REP_MONTHLY_SAMEDAY repeat type 
will work
+            // out the day from the start date
+          }
+        }
+      }
+      break;
+    case 'YEARLY':
+      $result['rep_type'] = REP_YEARLY;
+      break;
+    default:
+      trigger_error("FREQ=${rules['FREQ']} not supported by MRBS", 
E_USER_WARNING);
+      $unsupported_rules = TRUE;
+      break;
+  }
+  
+  if (isset($rules['interval']) && ($rules['interval'] > 1) && 
+      !in_array($rules['FREQ'], array('WEEKLY')))
+  {
+    trigger_error("MRBS does not support INTERVAL>1 with 
FREQ=${rules['FREQ']}", E_USER_WARNING);
+    $unsupported_rules = TRUE;
+  }
+  
+  if (isset($rules['UNTIL']))
+  {
+    // Strictly speaking "the value of the UNTIL rule part MUST have the same
+    // value type as the "DTSTART" property".   So we should really tell 
get_time()
+    // the value type.  But "if the "DTSTART" property is specified as a date 
with UTC
+    // time or a date with local time and time zone reference, then the UNTIL 
rule
+    // part MUST be specified as a date with UTC time" - so in nearly all cases
+    // supported by MRBS the value will be a UTC time.
+    $result['end_date'] = get_time($rules['UNTIL']);
+  }
+  elseif (isset($rules['COUNT']))
+  {
+    // It would be quite easy to support COUNT, but we haven't done so yet
+    trigger_error("COUNT not yet supported by MRBS");
+    $unsupported_rules = TRUE;
+  }
+  else
+  {
+    trigger_error("Indefinite repeats not yet supported by MRBS");
+    $unsupported_rules = TRUE;
+  }
+  
+  return (empty($unsupported_rules)) ? $result: FALSE;
+}
+
+
 // "Folds" lines longer than 75 octets.  Multi-byte safe.
 //
 // "Lines of text SHOULD NOT be longer than 75 octets, excluding the line
@@ -328,6 +561,13 @@
   return $str;
 }
 
+
+function ical_unescape_text($str)
+{
+  return stripcslashes($str);
+}
+
+
 // Escape text for use in an iCalendar quoted string
 function ical_escape_quoted_string($str)
 {
@@ -344,12 +584,52 @@
 }
 
 
+function ical_unescape_quoted_string($str)
+{
+  return trim($str, '"');
+}
+
+
+// Parse a content line which is a property (ie is inside a component).   
Returns
+// an associative array:
+//   'name'       the property name
+//   'params'     an associative array of parameters indexed by parameter name
+//   'value'      the property value.  The value will have escaping reversed
+function parse_ical_property($line)
+{
+  $result = array();
+  // First of all get the string up to the first colon or semicolon.   This 
will
+  // be the property name.   We also want to get the delimiter so that we know
+  // whether there are any parameters to come.   The split will return an array
+  // with three elements:  0 - the string before the delimiter, 1 - the 
delimiter
+  // and 2 the rest of the string
+  $tmp = preg_split('/([;:])/' , $line, 2, PREG_SPLIT_DELIM_CAPTURE);
+  $result['name'] = $tmp[0];
+  $params = array();
+  if ($tmp[1] != ':')
+  {
+    // Get all the property parameters
+    do 
+    {
+      $tmp = preg_split('/([;:])/' , $tmp[2], 2, PREG_SPLIT_DELIM_CAPTURE);
+      $param = array();
+      list($param_name, $param_value) = explode('=', $tmp[0], 2);
+      // The parameter value can be a quoted string, so get rid of any double 
quotes
+      $param[$param_name] = ical_unescape_quoted_string($param_value);
+    }
+    while ($tmp[1] != ':');
+  }
+  $result['params'] = $params;
+  $result['value'] = ical_unescape_text($tmp[2]);
+  return $result;
+}
+
+
 // Create an iCalendar Recurrence Rule
 function create_rrule($data)
 {
-  // Create an array which can be used to map day of the week numbers (0..6)
-  // onto days of the week as defined in RFC 5545
-  $RFC_5545_days = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
+  global $RFC_5545_days;
+
   $rule = '';
   if (!isset($data['rep_type']))
   {

Added: mrbs/branches/ics_import/web/import.php
===================================================================
--- mrbs/branches/ics_import/web/import.php                             (rev 0)
+++ mrbs/branches/ics_import/web/import.php     2012-01-23 14:35:01 UTC (rev 
2251)
@@ -0,0 +1,420 @@
+<?php
+// $Id$
+
+require_once "defaultincludes.inc";
+require_once "functions_ical.inc";
+require_once "mrbs_sql.inc";
+
+
+function get_room_id($location)
+{
+  global $area_room_order, $area_room_delimiter, $area_room_create, $test;
+  global $tbl_room, $tbl_area;
+  
+  // We cache the contents of the room and area tables so that we can do a test
+  // import.   It will also help a little with performance.
+  static $rooms = array();
+  static $areas = array();
+  static $room_ids = array();
+  static $area_ids = array();
+  
+  $sql = "SELECT id, room_name, area_id FROM $tbl_room";
+  $res = sql_query($sql);
+  if ($res === FALSE)
+  {
+    trigger_error(sql_error(), E_USER_WARNING);
+    fatal_error(FALSE, get_vocab("fatal_db_error"));
+  }
+  for ($i = 0; ($row = sql_mysql_row_keyed($res, $i)); $i++)
+  {
+    $rooms[] = $row;
+    $room_ids[] = $row['id'];
+  }
+  
+  $sql = "SELECT id, area_name FROM $tbl_area";
+  $res = sql_query($sql);
+  if ($res === FALSE)
+  {
+    trigger_error(sql_error(), E_USER_WARNING);
+    fatal_error(FALSE, get_vocab("fatal_db_error"));
+  }
+  for ($i = 0; ($row = sql_mysql_row_keyed($res, $i)); $i++)
+  {
+    $areas[] = $row;
+    $area_ids[] = $row['id'];
+  }
+  
+  // If there's no delimiter we assume we've just been given a room name (that 
will
+  // have to be unique).   Otherwise we split the location into its area and 
room parts
+  if (strpos($location, $area_room_delimiter) === FALSE)
+  {
+    $location_area = '';
+    $location_room = $location;
+  }
+  elseif ($area_room_order = 'area_room')
+  {
+    list($location_area, $location_room) = explode($area_room_delimiter, 
$location);
+  }
+  else
+  {
+    list($location_room, $location_area) = explode($area_room_delimiter, 
$location);
+  }
+  $location_area = trim($location_area);
+  $location_room = trim($location_room);
+  
+  // Now search the database for the room
+  
+  // Case 1:  we've just been given a room name, in which case we hope it 
happens
+  // to be unique, because if we find more than one we won't know which one is 
intended
+  // and if we don't find one at all we won't be able to create it because we 
won't 
+  // know which area to put it in.
+  if ($location_area == '')
+  {
+    $ids = array();
+    foreach ($rooms as $room)
+    {
+      if ($room['room_name'] == $location_room)
+      {
+        $ids[] = $room['id'];
+      }
+    }
+    if (count($ids) == 1)
+    {
+      return $ids[0];
+    }
+    elseif (count($ids) == 0)
+    {
+      echo "Room '$location_room' does not exist and cannot be added - no area 
given.<br>\n";
+      return FALSE;
+    }
+    else
+    {
+      echo "There is more than one room called '$location_room'.  Cannot 
choose which one without an area.<br>\n";
+      return FALSE;
+    }
+  }
+  // Case 2:  we've got an area and room name
+  else
+  {
+    // First of all get the area_id
+    $area_id = NULL;
+    foreach ($areas as $area)
+    {
+      if ($area['area_name'] == $location_area)
+      {
+        $area_id = $area['id'];
+        break;
+      }
+    }
+    if (!isset($area_id))
+    {
+      if (!$area_room_create)
+      {
+        echo get_vocab("area_does_not_exist") . " '$location_area'<br>\n";
+        return FALSE;
+      }
+      else
+      {
+        echo get_vocab("creating_new_area") . " '$location_area'<br>\n";
+        if ($test)
+        {
+          $area_id = max($area_ids) + 1;
+        }
+        else
+        {
+          $error = '';
+          $area_id = mrbsAddArea($location_area, $error);
+          if ($area_id === FALSE)
+          {
+            echo get_vocab("could_not_create_area") . " 
'$location_area'<br>\n";
+            return FALSE;
+          }
+        }
+        $areas[] = array('id' => $area_id, 'area_name' => $location_area);
+        $area_ids[] = $area_id;
+      }
+    }
+    // Now we've got the area_id we can find the room_id
+    $room_id = NULL;
+    foreach ($rooms as $room)
+    {
+      if (($room['room_name'] == $location_room) && ($room['area_id'] == 
$area_id))
+      {
+        $room_id = $room['id'];
+        break;
+      }
+    }
+    if (!isset($room_id))
+    {
+      if (!$area_room_create)
+      {
+        echo get_vocab("area") . " $location_area. " . 
+             get_vocab("room_does_not_exist") . " '$location_room'<br>\n";
+        return FALSE;
+      }
+      else
+      {
+        echo get_vocab("area") . " $location_area. " .
+             get_vocab("creating_new_room") . " '$location_room'<br>\n";
+        if ($test)
+        {
+          $room_id = max($room_ids) + 1;
+        }
+        else
+        {
+          $error = '';
+          $room_id = mrbsAddRoom($location_room, $area_id, $error);
+          if ($room_id === FALSE)
+          {
+            echo get_vocab("could_not_create_room") . " 
'$location_room'<br>\n";
+            return FALSE;
+          }
+        }
+        $rooms[] = array('id' => $room_id, 'room_name' => $location_room, 
'area_id' => $area_id);
+        $room_ids[] = $room_id;
+      }
+    }
+    return $room_id;
+  }
+}
+
+
+function process_event($vevent)
+{
+  $booking = array();
+  $booking['status'] = 0;
+  $booking['rep_type'] = REP_NONE;
+  $properties = array();
+  // Parse all the lines first because we'll need to get the start date
+  // for calculating some of the other settings
+  foreach ($vevent as $line)
+  {
+    $property = parse_ical_property($line);
+    $properties[$property['name']] = array('params' => $property['params'],
+                                           'value' => $property['value']);
+  }
+  // Get the start time and UID, because we'll need them later
+  if (!isset($properties['DTSTART']))
+  {
+    trigger_error("No DTSTART", E_USER_WARNING);
+  }
+  else
+  {
+    $booking['start_time'] = get_time($properties['DTSTART']['value'],
+                                      $properties['DTSTART']['params']);
+  }
+  $booking['ical_uid'] = (isset($properties['UID'])) ? 
$properties['UID']['value'] : "unknown UID";
+  // Now go through the rest of the properties
+  foreach($properties as $name => $details)
+  {
+    switch ($name)
+    {
+      case 'SUMMARY':
+        $booking['name'] = $details['value'];
+        break;
+      case 'DESCRIPTION':
+        $booking['description'] = $details['value'];
+        break;
+      case 'LOCATION':
+        $booking['room_id'] = get_room_id($details['value']);
+        break;
+      case 'DTEND':
+        $booking['end_time'] = get_time($details['value'], $details['params']);
+        break;
+      case 'DURATION':
+        trigger_error("DURATION not yet supported by MRBS", E_USER_WARNING);
+        break;
+      case 'RRULE':
+        $repeat_details = get_repeat_details($details['value'], 
$booking['start_time']);
+        if ($repeat_details === FALSE)
+        {
+          echo "Could not import event with UID ${booking['ical_uid']}.   
Recurrence rule not supported";
+          return;
+        }
+        else
+        {
+          foreach ($repeat_details as $key => $value)
+          {
+            $booking[$key] = $value;
+          }
+        }
+        break;
+      case 'CLASS':
+        if (in_array($details['value'], array('PRIVATE', 'CONFIDENTIAL')))
+        {
+          $booking['status'] |= STATUS_PRIVATE;
+        }
+        break;
+      case 'STATUS':
+        if ($details['value'] == 'TENTATIVE')
+        {
+          $booking['status'] |= STATUS_TENTATIVE;
+        }
+        break;
+      case 'SEQUENCE':
+        $booking['ical_sequence'] = $details['value'];
+        break;
+    }
+  }
+
+  mrbsMakeBooking($booking);
+}
+
+
+// Check the user is authorised for this page
+checkAuthorised();
+
+print_header($day, $month, $year, $area, $room);
+
+$import = get_form_var('import', 'string');
+$test = get_form_var('test', 'string');
+$area_room_order = get_form_var('area_room_order', 'string');
+$area_room_delimiter = get_form_var('area_room_delimiter', 'string');
+$area_room_create = get_form_var('area_room_create', 'string');
+
+// Set defaults
+if (!isset($area_room_order))
+{
+  $area_room_order = 'area_room';
+}
+if (!isset($area_room_delimiter))
+{
+  $area_room_delimiter = ';';
+}
+if (!isset($area_room_create))
+{
+  $area_room_crete = FALSE;
+}
+
+// PHASE 2 - Process the files
+// ---------------------------
+
+if (!empty($test) || !empty($import))
+{
+  if ($_FILES['ics_file']['error'] !== UPLOAD_ERR_OK)
+  {
+    echo "<p>\n";
+    echo get_vocab("upload_failed");
+    switch($_FILES['ics_file']['error'])
+    {
+      case UPLOAD_ERR_INI_SIZE:
+        echo "<br>\n";
+        echo get_vocab("max_allowed_file_size") . " " . 
ini_get('upload_max_filesize');
+        break;
+      case UPLOAD_ERR_NO_FILE:
+        echo "<br>\n";
+        echo get_vocab("no_file");
+        break;
+      default:
+        // None of the other possible errors would make much sense to the 
user, but should be reported
+        trigger_error($_FILES['ics_file']['error'], E_USER_NOTICE);
+        break;
+    }
+    echo "</p>\n";
+  }
+  elseif (!is_uploaded_file($_FILES['ics_file']['tmp_name']))
+  {
+    // This should not happen and if it does may mean that somebody is messing 
about
+    echo "<p>\n";
+    echo get_vocab("upload_failed");
+    echo "</p>\n";
+    trigger_error("Attempt to import a file that has not been uploaded", 
E_USER_WARNING);
+  }
+  // We've got a file
+  else
+  {
+    $vcalendar = file_get_contents($_FILES['ics_file']['tmp_name']);
+    if ($vcalendar !== FALSE)
+    {
+      $lines = explode("\r\n", ical_unfold($vcalendar));
+      // Check that this bears some resemblance to a VCALENDAR
+      if ((array_shift($lines) != "BEGIN:VCALENDAR") ||
+          (array_pop($lines) != "END:VCALENDAR"))
+      {
+        echo "<p>\n" . get_vocab("badly_formed_ics") . "</p>\n";
+      }
+      // Looks OK - find all the VEVENTS which we are going to put in a two 
dimensional array -
+      // each event will consist of an array of lines making up the event.  
(Note - we
+      // are going to ignore any VTIMEZONE definitions.   We will honour TZID 
data in
+      // a VEVENT but we will use the PHP definition of the timezone)
+      else
+      {
+        $vevents = array();
+        while ($line = array_shift($lines))
+        {
+          if ($line == "BEGIN:VEVENT")
+          {
+            $vevent = array();
+            while (($vevent_line = array_shift($lines)) && ($vevent_line != 
"END:VEVENT"))
+            {
+                $vevent[] = $vevent_line;
+            }
+            $vevents[] = $vevent;
+          }
+        }
+      }
+      // Process each event, putting it in the database
+      foreach ($vevents as $vevent)
+      {
+        process_event($vevent);
+      }
+    }
+  }
+}
+
+// PHASE 1 - Get the user input
+// ----------------------------
+echo "<form class=\"form_general\" method=\"POST\" 
enctype=\"multipart/form-data\" action=\"" . 
htmlspecialchars(basename($PHP_SELF)) . "\">\n";
+
+echo "<fieldset class=\"admin\">\n";
+echo "<legend>" . get_vocab("import_icalendar") . "</legend>\n";
+
+echo "<p>\n" . get_vocab("import_intro") . "</p>\n";
+  
+echo "<div>\n";
+echo "<label for=\"ics_file\">" . get_vocab("file_name") . ":</label>\n";
+echo "<input type=\"file\" name=\"ics_file\" id=\"ics_file\">\n";
+echo "</div>\n";
+
+echo "<fieldset>\n";
+echo "<legend>hhh</legend>\n";
+
+echo "<div>\n";
+echo "<label>" . get_vocab("area_room_order") . ":</label>\n";
+echo "<div class=\"group\">\n";
+echo "<label><input type=\"radio\" name=\"area_room_order\" 
value=\"area_room\"" .
+     (($area_room_order == "area_room") ? " checked=\"checked\"" : "") . ">" .
+     get_vocab("area_room") . "</label>\n";
+echo "<label><input type=\"radio\" name=\"area_room_order\" 
value=\"room_area\"" .
+     (($area_room_order == "room_area") ? " checked=\"checked\"" : "") . ">" .
+     get_vocab("room_area") . "</label>\n";
+echo "</div>\n";
+echo "</div>\n";
+
+echo "<div>\n";
+echo "<label for=\"area_room_delimiter\">" . get_vocab("area_room_delimiter") 
. ":</label>\n";
+echo "<input type=\"text\" name=\"area_room_delimiter\" 
id=\"area_room_delimiter\"" .
+     " value=\"" . htmlspecialchars($area_room_delimiter) . "\">\n";
+echo "</div>\n";
+
+echo "<div>\n";
+echo "<label for=\"area_room_create\">" . get_vocab("area_room_create") . 
":</label>\n";
+echo "<input type=\"checkbox\" name=\"area_room_create\" 
id=\"area_room_create\" value=\"yes\"" .
+     (($area_room_create) ? " checked=\"checked\"" : "") . 
+     ">\n";
+echo "</div>\n";
+
+echo "</fieldset>\n";
+
+// The Submit button
+echo "<div id=\"import_submit\">\n";
+echo "<input class=\"submit default_action\" type=\"submit\" name=\"test\" 
value=\"" . get_vocab("test") . "\">\n";
+echo "<input class=\"submit\" type=\"submit\" name=\"import\" value=\"" . 
get_vocab("import") . "\">\n";
+echo "</div>\n";
+
+echo "</fieldset>\n";
+
+echo "</form>\n";
+  
+require_once "trailer.inc";
+?>
\ No newline at end of file


Property changes on: mrbs/branches/ics_import/web/import.php
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Modified: mrbs/branches/ics_import/web/lang.en
===================================================================
--- mrbs/branches/ics_import/web/lang.en        2012-01-19 13:50:50 UTC (rev 
2250)
+++ mrbs/branches/ics_import/web/lang.en        2012-01-23 14:35:01 UTC (rev 
2251)
@@ -416,6 +416,31 @@
 $vocab["please_contact"]     = "Please contact ";
 $vocab["for_any_questions"]  = "for any questions that aren't answered here.";
 
+// Used in import.php
+$vocab["import_icalendar"]      = "Import an iCalendar file";
+$vocab["import_intro"]          = "This form allows you to import an RFC 5545 
compliant " .
+                                  "iCalendar file into MRBS.   Only those 
repeating events " .
+                                  "that have a recurrence rule with an 
equivalent repeat type in " .
+                                  "MRBS will be imported.";
+$vocab["file_name"]             = "File";
+$vocab["import"]                = "Import";
+$vocab["test"]                  = "Test";
+$vocab["upload_failed"]         = "Upload failed";
+$vocab["max_allowed_file_size"] = "The maximum allowed file size is";
+$vocab["no_file"]               = "No file was uploaded";
+$vocab["badly_formed_ics"]      = "Badly formed VCALENDAR file";
+$vocab["area_room_order"]       = "Order";
+$vocab["area_room"]             = "Area-Room";
+$vocab["room_area"]             = "Room-Area";
+$vocab["area_room_delimiter"]   = "Delimiter";
+$vocab["area_room_create"]      = "Create rooms if necessary";
+$vocab["area_does_not_exist"]   = "Non-existent area:";
+$vocab["room_does_not_exist"]   = "Non-existent room:";
+$vocab["creating_new_area"]     = "Creating new area:";
+$vocab["creating_new_room"]     = "Creating new room:";
+$vocab["could_not_create_area"] = "Could not create area";
+$vocab["could_not_create_room"] = "Could not create room";
+
 // Used in mysql.inc AND pgsql.inc
 $vocab["failed_connect_db"]  = "Fatal error: failed to connect to database";
 

Modified: mrbs/branches/ics_import/web/mrbs_auth.inc
===================================================================
--- mrbs/branches/ics_import/web/mrbs_auth.inc  2012-01-19 13:50:50 UTC (rev 
2250)
+++ mrbs/branches/ics_import/web/mrbs_auth.inc  2012-01-23 14:35:01 UTC (rev 
2251)
@@ -39,6 +39,7 @@
 $page_level['add.php']                   = 2;
 $page_level['del.php']                   = 2;
 $page_level['del_entry_ajax.php']        = 2;
+$page_level['import.php']                = 2;
 
 
 /* getAuthorised($level)

Modified: mrbs/branches/ics_import/web/mrbs_sql.inc
===================================================================
--- mrbs/branches/ics_import/web/mrbs_sql.inc   2012-01-19 13:50:50 UTC (rev 
2250)
+++ mrbs/branches/ics_import/web/mrbs_sql.inc   2012-01-23 14:35:01 UTC (rev 
2251)
@@ -1047,4 +1047,140 @@
   return $id;
 }
 
+
+// Adds an area, returning the new id, or FALSE on failute with the
+// error in $error
+function mrbsAddArea($name, &$error)
+{
+  global $maxlength, $tbl_area, $area_defaults, $boolean_fields;
+  
+  // First of all check that we've got a name
+  if (!isset($name) || ($name === ''))
+  {
+    $error = "empty_name";
+    return FALSE;
+  }
+  
+  // Truncate the name field to the maximum length as a precaution.
+  $name = substr($name, 0, $maxlength['area.area_name']);
+  $area_name_q = addslashes($name);
+  // Acquire a mutex to lock out others who might be editing the area
+  if (!sql_mutex_lock("$tbl_area"))
+  {
+    fatal_error(TRUE, get_vocab("failed_to_acquire"));
+  }
+  // Check that the area name is unique
+  if (sql_query1("SELECT COUNT(*) FROM $tbl_area WHERE 
area_name='$area_name_q' LIMIT 1") > 0)
+  {
+    sql_mutex_unlock("$tbl_area");
+    $error = "invalid_area_name";
+    return FALSE;
+  }
+  // If so, insert the area into the database.   We insert the area name that
+  // we have been given, together with the default values for the per-area 
settings
+
+  // Build arrays of data to be inserted into the table
+  $sql_col = array();
+  $sql_val = array();
+  // Get the information about the fields in the room table
+  $fields = sql_field_info($tbl_area);
+  // Loop through the fields and build up the arrays
+  foreach ($fields as $field)
+  {
+    $key = $field['name'];
+    switch ($key)
+    {
+    case 'area_name':
+      $sql_col[] = $key;
+      $sql_val[] = "'$area_name_q'";
+      break;
+    default:
+      if (array_key_exists($key, $area_defaults))
+      {
+        $sql_col[] = $key;
+        if (in_array($key, $boolean_fields['area']))
+        {
+          $sql_val[] = ($area_defaults[$key]) ? 1 : 0;
+        }
+        elseif ($field['nature'] == 'integer')
+        {
+          $sql_val[] = $area_defaults[$key];
+        }
+        else
+        {
+          $sql_val[] = "'" . addslashes($area_defaults[$key]) . "'";
+        }
+      }
+      break;
+    }
+  }
+  $sql = "INSERT INTO $tbl_area (" . implode(', ',$sql_col) . ") VALUES (" . 
implode(', ',$sql_val) . ")";
+  if (sql_command($sql) < 0)
+  {
+    trigger_error(sql_error(), E_USER_WARNING);
+    fatal_error(TRUE, get_vocab("fatal_db_error"));
+  }
+  $area = sql_insert_id($tbl_area, 'id');
+
+  // Release the mutex
+  sql_mutex_unlock("$tbl_area");
+  return $area;
+}
+
+
+// Adds a room, returning the new id, or FALSE on failute with the
+// error in $error
+function mrbsAddRoom($name, $area, &$error, $description='', $capacity='')
+{
+  global $maxlength, $tbl_room;
+  
+  // First of all check that we've got a name
+  if (!isset($name) || ($name === ''))
+  {
+    $error = "empty_name";
+    return FALSE;
+  }
+  
+  // Truncate the name and description fields to the maximum length as a 
precaution.
+  $name = substr($name, 0, $maxlength['room.room_name']);
+  $description = substr($description, 0, $maxlength['room.description']);
+  // Add SQL escaping
+  $room_name_q = addslashes($name);
+  $description_q = addslashes($description);
+  if (empty($capacity))
+  {
+    $capacity = 0;
+  }
+  // Acquire a mutex to lock out others who might be editing rooms
+  if (!sql_mutex_lock("$tbl_room"))
+  {
+    fatal_error(TRUE, get_vocab("failed_to_acquire"));
+  }
+  // Check that the room name is unique within the area
+  if (sql_query1("SELECT COUNT(*) FROM $tbl_room WHERE 
room_name='$room_name_q' AND area_id=$area LIMIT 1") > 0)
+  {
+    sql_mutex_unlock("$tbl_room");
+    $error = "invalid_room_name";
+    return FALSE;
+  }
+  // If so, insert the room into the database
+  $sql = "INSERT INTO $tbl_room (room_name, sort_key, area_id, description, 
capacity)
+          VALUES ('$room_name_q', '$room_name_q', $area, 
'$description_q',$capacity)";
+  if (sql_command($sql) < 0)
+  {
+    trigger_error(sql_error(), E_USER_WARNING);
+    fatal_error(TRUE, get_vocab("fatal_db_error"));
+  }
+  $room = sql_insert_id($tbl_room, 'id');
+  // Release the mutex
+  sql_mutex_unlock("$tbl_room");
+  return $room;
+}
+
+
+function mrbsMakeBooking($data)
+{
+  return;
+}
+
 ?>

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Mrbs-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mrbs-commits

Reply via email to