--- orig/recipe.module	2005-09-20 18:57:43.463607816 +0000
+++ recipe.module	2005-09-20 18:55:39.442461896 +0000
@@ -28,7 +28,7 @@
  * Implementation of hook_perm().
  */
 function recipe_perm() {
-  return array ("create recipes", 'edit own recipes');
+  return array ("create recipes", 'edit own recipes', 'import recipes');
 }
 
 /**
@@ -169,6 +169,11 @@
       'type' => MENU_CALLBACK,
       'access' => user_access('access content')
     );
+    $items[] = array('path' => 'recipe_import',
+              'title' => t('recipe import'),
+              'callback' => 'recipe_import_page',
+      'access' => user_access('import recipes'),
+      'type' => MENU_NORMAL_ITEM);
   }
   else {
     theme_add_style('modules/recipe/recipe.css');
@@ -702,5 +707,134 @@
   return $units_array[$string];
 }
 
+function recipe_import_page() {
+  unset($GLOBALS['error'], $GLOBALS['recipe'], $GLOBALS['recipes'], $GLOBALS['data_string'], $GLOBALS['yield']);
+  global $error, $recipe, $recipes, $data_string, $yield;
+  if ($path = $_FILES['edit']['tmp_name']['recipe_import_file']) {
+    $data = file_get_contents($path);
+
+    // parse the data:
+    $xml_parser = drupal_xml_parser_create($data);
+    xml_set_element_handler($xml_parser, 'recipe_import_element_start', 'recipe_import_element_end');
+    xml_set_character_data_handler($xml_parser, 'recipe_import_element_data');
+
+    if (!xml_parse($xml_parser, $data, 1)) {
+      $message = t('Failed to parse RecipeML feed %site: %error at line %line.', 
+                   array(
+                   '%site' => theme('placeholder', $feed['title']), 
+                   '%error' => xml_error_string(xml_get_error_code($xml_parser)), 
+                   '%line' => xml_get_current_line_number($xml_parser)));
+      watchdog('recipe_import', $message, WATCHDOG_WARNING);
+      drupal_set_message($message, 'error');
+    }
+    xml_parser_free($xml_parser);
+    
+    $recipe = node_validate($recipe, $error);
+
+    if (!node_access("create", $node)) {
+        $error['access'] = message_access();
+    }
+    $output .= '<pre>';
+    if ($error) {
+      $output .= ($error);
+    }
+    else {
+      if ($_POST['op'] == t('Import')) {
+        foreach($recipes as $recipe) {
+          node_save($recipe);
+          if ($recipe->nid) {
+            $output .= "saved ". l($recipe->title, "node/{$recipe->nid}")."<br />";
+          } else {
+            $output .= "could not save {$recipe->title}<br />";
+          }
+        }
+      }
+    }
+    $output .= '</pre>';
+  }
+  $output .= form_file(t('RecipeML File'), "recipe_import_file", 34, t("A Recipe in RecipeML format, see http://www.formatdata.com/recipeml"));
+  $output .= form_submit(t('Import'));
+  $output = form($output, 'post', 0, array("enctype" => "multipart/form-data"));
+  echo theme('page', $output);
+}
+
+/**
+ * Call-back function used by the XML parser.
+ */
+function recipe_import_element_start($parser, $name, $attributes) {
+  global $recipe, $yield, $ingredient;
+
+  switch ($name) {
+    case 'RECIPE':
+      $recipe = new StdClass();
+      $recipe->type = "recipe";
+      break;
+    case 'ING':
+      $ingredient = new StdClass();
+      break;
+    case 'YIELD':
+      $yield = true;
+      break;
+  }
+}
+
+/**
+ * Call-back function used by the XML parser.
+ */
+function recipe_import_element_end($parser, $name) {
+  global $ingredient, $yield, $data_string, $recipes, $recipe, $user;
+
+  switch ($name) {
+      case 'RECIPE':
+        $recipe->uid = $user->uid;
+        if ($recipe->yield == 0) $recipe->yield = 1;
+        if (!$recipe->notes) $recipe->notes = "Imported from RecipeML file";
+        if (!$recipe->title) {
+          $recipe->title = "RecipeML autotitle";
+        } else {
+          if (!$recipe->teaser) $recipe->teaser= $recipe->title." recipe";
+          if (!$recipe->body) $recipe->body = $recipe->title." recipe";
+        }
+        $recipes[] = $recipe;
+        break;
+      case 'ING':
+        $recipe->ingredients[] = $ingredient;
+        break;
+      case 'YIELD':
+        $yield = false;
+        break;
+      case "TITLE":
+        $recipe->title = trim($data_string);
+        break;
+      case 'QTY':
+        if ($yield) $recipe->yield = trim($data_string);
+        else $ingredient->quantity = trim($data_string);
+        break;
+      case 'UNIT':
+        if ($unit = recipe_unit_from_name(trim($data_string)))
+          $ingredient->unit_id = $unit->id;
+        break;
+      case 'ITEM':
+        $ingredient->name = trim($data_string);
+        break;
+      case 'YIELD':
+        $yield = false;
+        break;
+      case 'DIRECTIONS':
+        $recipe->instructions .= trim($data_string);
+        break;
+      case 'STEP':
+        $recipe->instructions .= trim($data_string)."\n";
+  }
+  $data_string = '';
+}
+
+/**
+ * Call-back function used by the XML parser.
+ */
+function recipe_import_element_data($parser, $data) {
+  global $data_string;
+  $data_string .= $data;
+}
 
 ?>
