Index: amazon.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/amazon/amazon.module,v
retrieving revision 1.27.2.12
diff -u -r1.27.2.12 amazon.module
--- amazon.module	12 Sep 2008 23:22:20 -0000	1.27.2.12
+++ amazon.module	4 Nov 2008 03:25:14 -0000
@@ -15,6 +15,8 @@
 // Other common sizes include SwatchImage, TinyImage, and ThumbnailImage.
 define('AMAZON_IMAGE_SIZES', 'SmallImage,MediumImage,LargeImage');
 
+define('AMAZON_DOS_LIMIT', 10);
+
 /**
  * Implementation of hook_menu. Adds the url path for the Amazon
  * settings page.
@@ -237,7 +237,11 @@ function amazon_item_lookup($item_ids =
     }
   }
   $items_from_web = amazon_item_lookup_from_web($items_to_fetch);
-  return array_merge($items, $items_from_web);
+
+  foreach ($items_from_web as $asin => $item) {
+    $items[$asin] = $item;
+  }
+  return $items;
 }

 function amazon_item_lookup_from_web($item_ids = array()) {
-  // We do this to avoid bombing Amazon.com with 1000 item requests.
-  $amazon_limit = 10;
-  $asins = array();
+  // We chunk requests into size AMAZON_DOS_LIMIT to avoid bombing Amazon with thousands of item requests.
   $results = array();
-  foreach ($item_ids as $asin) {
-    $asins[] = $asin;
-    if (count($asins) >= $amazon_limit || count($asins) == count($item_ids)) {
+  if ($count = count($item_ids)) {
+    for ($start = 0; $start < $count; $start += AMAZON_DOS_LIMIT) {
+      $asins = array_slice($item_ids, $start, AMAZON_DOS_LIMIT);
       $results += _amazon_item_batch_lookup_from_web($asins);
-      $asins = array();
     }
   }
   return $results;
@@ -257,19 +256,49 @@
 
 function _amazon_item_batch_lookup_from_web($item_ids = array()) {
   if (!empty($item_ids)) {
-    $params = array(
-      'ItemId' => implode(',', $item_ids),
-      'ResponseGroup' => 'Large',
-    );
-    $results = amazon_http_request('ItemLookup', $params);
-    if (!empty($results->Error)) {
-      return FALSE;
+    $eans = array(); 
+    $asins = array();
+    // Partition identifiers into two groups: ASINs (10 characters) and EANs (13 characters)
+    foreach ($item_ids as $item_id) {
+      if (strlen($item_id) == 13) {
+        $eans[] = $item_id;
+      }
+      else {
+        $asins[] = $item_id;
+      }
+    }
+    $results = array();
+    // Batch retrieve all the products identified by a 10 character ASIN 
+    if (!empty($asins)) {
+      $params = array(
+        'IdType' => 'ASIN',
+        'ItemId' => implode(',', $asins),
+        'ResponseGroup' => 'Large',
+      );
+      $results[] = amazon_http_request('ItemLookup', $params);
+    }
+    // Batch retrieve all the products identified by a 13 character EAN 
+    if (!empty($eans)) {
+      $params = array(
+        'IdType' => 'EAN',
+        'SearchIndex' => variable_get('amazon_locale_ean_search_index', 'Books'),
+        'ItemId' => implode(',', $eans),
+        'ResponseGroup' => 'Large',
+      );
+      $results[] = amazon_http_request('ItemLookup', $params);
     }
     $items = array();
-    foreach($results->Items->Item as $xml) {
-      $item = amazon_item_clean_xml($xml);
-      amazon_item_save($item);
-      $items[$item['asin']] = $item;
+    // Merge the ASIN and EAN result sets together
+    foreach ($results as $result) {
+      // Return FALSE if either result set fails  
+      if (!empty($result->Error)) {
+        return FALSE;
+      }
+      foreach($result->Items->Item as $xml) {
+        $item = amazon_item_clean_xml($xml);
+        amazon_item_save($item);
+        $items[$item['asin']] = $item;
+      }
     }
 
     return $items;
Index: amazon.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/amazon/amazon.admin.inc,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 amazon.admin.inc
--- amazon.admin.inc	28 Jun 2008 18:12:14 -0000	1.1.2.5
+++ amazon.admin.inc	4 Nov 2008 03:25:14 -0000
@@ -14,6 +14,64 @@
     '#description' => t('Amazon.com uses separate product databases and Ecommerce features in different locales; pricing and availability information, as well as product categorization, differs from one locale to the next. Be sure to select the locale your site will be running in.'),
   );
 
+  $options = array(
+    'All' => 'All',
+    'Apparel' => 'Apparel',
+    'Automotive' => 'Automotive',
+    'Baby' => 'Baby',
+    'Beauty' => 'Beauty',
+    'Blended' => 'Blended',
+    'Books' => 'Books',
+    'Classical' => 'Classical',
+    'DigitalMusic' => 'DigitalMusic',
+    'DVD' => 'DVD',
+    'Electronics' => 'Electronics',
+    'ForeignBooks' => 'ForeignBooks',
+    'GourmetFood' => 'GourmetFood',
+    'Grocery' => 'Grocery',
+    'HealthPersonalCare' => 'HealthPersonalCare',
+    'Hobbies' => 'Hobbies',
+    'HomeGarden' => 'HomeGarden',
+    'HomeImprovement' => 'HomeImprovement',
+    'Industrial' => 'Industrial',
+    'Jewelry' => 'Jewelry',
+    'KindleStore' => 'KindleStore',
+    'Kitchen' => 'Kitchen',
+    'Magazines' => 'Magazines',
+    'Merchants' => 'Merchants',
+    'Miscellaneous' => 'Miscellaneous',
+    'MP3Downloads' => 'MP3Downloads',
+    'Music' => 'Music',
+    'MusicalInstruments' => 'MusicalInstruments',
+    'MusicTracks' => 'MusicTracks',
+    'OfficeProducts' => 'OfficeProducts',
+    'OutdoorLiving' => 'OutdoorLiving',
+    'PCHardware' => 'PCHardware',
+    'PetSupplies' => 'PetSupplies',
+    'Photo' => 'Photo',
+    'Shoes' => 'Shoes',
+    'SilverMerchant' => 'SilverMerchant',
+    'Software' => 'Software',
+    'SoftwareVideoGames' => 'SoftwareVideoGames',
+    'SportingGoods' => 'SportingGoods',
+    'Tools' => 'Tools',
+    'Toys' => 'Toys',
+    'VHS' => 'VHS',
+    'Video' => 'Video',
+    'VideoGames' => 'VideoGames',
+    'Watches' => 'Watches',
+    'Wireless' => 'Wireless',
+    'WirelessAccessories' => 'WirelessAccessories',
+  );
+  $form['amazon_locale_ean_search_index'] = array(
+    '#type' => 'select',
+    '#title' => t('EAN search index'),
+    '#default_value' => variable_get('amazon_locale_ean_search_index', 'Books'),
+    '#options' => $options,
+    '#description' => t('A search index must be specified when looking up by a 13 character EAN. Amazon.com makes different search indices available in different locales. Be sure to select a search index available for your locale. Read the !amazon documentation for more. Note: the EAN search index is not used when looking up a 10 character ASIN/ISBN.', 
+      array("!amazon" => l("Search Index Support by Locale", 'http://docs.amazonwebservices.com/AWSECommerceService/2008-08-19/DG/index.html?APPNDX_SearchIndexValues.html')))
+  );
+  
   $form['amazon_associate_setting'] = array(
     '#type' => 'select',
     '#title' => t('Amazon referral settings'),
@@ -127,9 +185,15 @@
   return $form;
 }
 
+function amazon_test_form_validate($form, &$form_state) {
+  if (!preg_match("/^[0-9A-Z]{10}|[0-9A-Z]{13}$/i", $form_state['values']['asin'], $matches)) {
+    form_set_error('asin', t("Invalid identifier. The identifier must a valid ASIN/ISBN (exactly 10 characters long) or EAN (exactly 13 characters long)."));
+  }
+}
+
 function amazon_test_form_submit($form, &$form_state) {
-  $items = amazon_item_lookup($form_state['values']['asin']);
-  if (is_array($items)) {
+  $items = amazon_item_lookup($form_state['values']['asin'], TRUE);
+  if (!empty($items)) {
     $item = array_pop($items);
     amazon_item_delete($item['asin']);
     amazon_item_save($item);
@@ -140,4 +204,7 @@
     $form_state['amazon_item'] = $item;
     $form_state['rebuild'] = TRUE;
   }
+  else {
+    drupal_set_message(t("No item found with an identifier of %asin", array("%asin" => $form_state['values']['asin'])), 'error');
+  }
 }
Index: asin/asin.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/amazon/asin/asin.module,v
retrieving revision 1.2.2.3
diff -u -r1.2.2.3 asin.module
--- asin/asin.module	12 Sep 2008 23:22:21 -0000	1.2.2.3
+++ asin/asin.module	4 Nov 2008 03:25:14 -0000
@@ -85,16 +85,45 @@
 function asin_field($op, &$node, $field, &$items, $teaser, $page) {
   switch ($op) {
     case 'validate':
+      // Validate both EANs and ASINs
       $results = _asin_load_items($items);
       foreach ($items as $delta => $item) {
         if (is_array($item)) {
-          if (!empty($item['asin']) && empty($results[$item['asin']])) {
+          // Is there a result keyed by this identifier
+          $found = !empty($results[$item['asin']]);
+          if (!$found) {
+            // If not, look for an EAN that matches
+            foreach ($results as $result) {
+              if ($result['ean'] == $item['asin']) {
+                $found = TRUE;
+                break;
+              }
+            }
+          }
+          if (!empty($item['asin']) && !$found) {
             form_set_error($field['field_name'] .']['. $delta .'][asin', t('%name : No Amazon product with the ID %id could be located.', array('%name' => t($field['widget']['label']), '%id' => $item['asin'])));
           }
         }
       }
       return $items;
 
+    case 'presave':
+      // Convert any EANs into their ASIN equivalents 
+      $results = _asin_load_items($items);
+      foreach ($items as $delta => $item) {
+        if (is_array($item)) {
+          if (empty($results[$item['asin']])) {
+            foreach ($results as $result) {
+              if ($result['ean'] == $item['asin']) {
+                $items[$delta]['asin'] = $result['asin'];
+                break;
+              }
+            }
+          }
+        }
+      }
+      break;
+      
     case 'load':
       $results = _asin_load_items($items);
       foreach ($items as $delta => $item) {
