, released under the GNU GPL //20030203/Jaap van Ganswijk, adapted for the heavy version //20030630/Jaap van Ganswijk, adapted further //20030717/Jaap van Ganswijk, expanded further, this will be released as amazonh3.php //20030912/Jaap van Ganswijk, fixed the 'register global' issue that a lot of people had trouble with //20030912/Jaap van Ganswijk, found an excessive ' that caused trouble remembering the product category //20030912/Jaap van Ganswijk, turned $pagefr0 back into $page (so base 1 instead of base 0, makes script clearer) //20030912/Jaap van Ganswijk, tried to explain the associate ID issue better //20030912/Jaap van Ganswijk, in case of the UK locale I show the USA product categories, which looks slightly better //20030912/Jaap van Ganswijk, in data.php I have disabled Japan, because the script can't really support it //20030912/Jaap van Ganswijk, in language.php I fixed a spelling mistake in 'buecher USA' //20031125/Jaap van Ganswijk, commented out the hidden language and locale fields in the form //20040129/Ted Knudson remarked that looking for things like 'kitchen design' didn't work properly // and so I added urlencode() at three places in the script //20040202/Tatiana Vygurska found some errors: //20040202/Jaap van Ganswijk, turned $pagefr0 back to $page in the link to the previous page //20040202/Jaap van Ganswijk, declared $locale global in function printProduct()! //20040408/JvG, removed the v=2.1 parameter //20040715/JvG, added some suggestions by Wim Roffel $mtime0=getmicrotime(); //time at start //The following code should fix the "global register"'s problem //that a lot of people had problems with, due to the fact //that the newest PHP versions aren't compatible with the older ones. //For details, see the PHP manual: //http://www.php.net/manual/en/configuration.directives.php#ini.register-globals //You can also solve this problem more rigorously by adding a file to your directory //called .htaccess with the line 'php_flag register_globals on' // if ($_GET) { $language =$_GET['language' ]; $locale =$_GET['locale' ]; $mode =$_GET['mode' ]; $page =$_GET['page' ]; $search =$_GET['search' ]; $searchtype=$_GET['searchtype']; $show_array=$_GET['show_array']; $show_url =$_GET['show_url' ]; $show_xml =$_GET['show_xml' ]; $type =$_GET['type' ]; } include "data.php"; //static data about Amazon (servers, search fields) include "language.php"; //translate the output to the prefered language of the user //set these to correspond with your site //the user can overrule them $Adefault=array( 'language' =>'en', //what language to render the page in 'locale' =>'us', //which country's products? 'mode' =>'books', //what product category? 'page' =>'1', //first page is 1 not 0 'search' =>'Machiavelli', //what to search for? 'searchtype'=>'KeywordSearch', //what kind of search? 'show_array'=>false, //debug: show complete array? 'show_url' =>false, //debug: show XML request url to be send to Amazon? 'show_xml' =>false, //debug: show incoming XML code? 'type' =>'lite', //heavy will cause Amazon to send a much bigger (typically six times bigger) file ); //change the debug options to true if you want to activate them //or call the script with '?..&show_xml=true' at the end of the URL //The PowerSearch can consist of upto 3 terms //separated by a '+' or '%20' like 'cat%20dog' //alternatives: //-'title:"civil+engineering"' //-'039480001X' - for AsinSearch, gives Seuss' "The Cat in the Hat" //See Amazon's docs about this // //for alternative languages, locales, product categories and search types //see the arrays below $Aassociates_id=array( 'de' => 'chipdir00' , // <-- replace chipdir00 with your amazon.de associate ID, or leave it as it is 'fr' => 'chipdir010', // <-- replace chipdir010 with your amazon.fr associate ID, or leave it as it is 'jp' => 'INVALID' , // <-- replace INVALID with your amazon.co.jp associate ID, or leave it as it is 'uk' => 'chipdir03' , // <-- replace chipdir03 with your amazon.co.uk associate ID, or leave it as it is 'us' => 'chipdir' , // <-- replace chipdir with your amazon.com associate ID ); //If you haven't gotten your own associate ID yet, get it from: //http://associates.amazon.com/exec/panama/associates/apply // //Normally you will want to start selling books via Amazon.com only, //just to see if it works and pays well (which it normally doesn't). // //You can save yourself a lot of trouble by not applying for an associate ID //at the other local Amazon sites yet, but leaving mine in for the time being //and perhaps I'll make a few pounds, euro's and/or yen. As soon as I would //receive a noticable amount of cash I'll track you down an will warn you //to get your own ID's there. // //please note that all those local Amazon's send out all of their communications //in their local languages, so French, German and Japanese for example and //that you first have to earn enough money per branch before you get paid. //And the Japanese branch only seems to pay in gift-certificates, so you'd //have to buy Japanese books for example. // //if you want to disable any of the foreign branches, please do so in the //file data.php, but please consider that we're living in an ever better //connected world and sometime later you might want to add them again //if only as a service to your visitors. //other flags: $f_rich =true; //when set to true this will convert the URL so you'll get 7.5% on qualifying books instead of 5%. It doesn't work yet outside of the USA. //change it to false when you prefer to get only 5% ;-) //see http://forums.prospero.com/n/mb/message.asp?webtag=am-assosdev&msg=6.1&ctx=0, or search the forum for 'nosim' //This is only helpful for certain books //correction: keep this option set to true, to prevent the showing of Amazon's annoying distraction pages. $f_user_search=true; //add a user search form and allow user searches? //============================================================================== //==You don't have to change anything after this line, to start earning money.== //============================================================================== //if the user hasn't overruled them yet, use the default if (!isset($language )) $language =$Adefault['language' ]; //20040815: isset()'s added if (!isset($locale )) $locale =$Adefault['locale' ]; if (!isset($mode )) $mode =$Adefault['mode' ]; if (!isset($page )) $page =$Adefault['page' ]; if (!isset($search )) $search =$Adefault['search' ]; if (!isset($searchtype)) $searchtype=$Adefault['searchtype']; if (!isset($show_url )) $show_url =$Adefault['show_url' ]; if (!isset($show_xml )) $show_xml =$Adefault['show_xml' ]; if (!isset($show_array)) $show_array=$Adefault['show_array']; if (!isset($type )) $type =$Adefault['type' ]; //use which servers? $norserver=$Aserver[$locale]['nor']; $xmlserver=$Aserver[$locale]['xml']; $dev_token='D2WMCOIPS9D14E'; //you can replace this with your own developer token if you have changed the script a lot //get one from http://associates.amazon.com/exec/panama/associates/join/developer/application.html //see: //http://forums.prospero.com/n/mb/message.asp?webtag=am-assocdevxml&msg=378.1&ctx=0 //form the URL to send to Amazon as a search request $file="$xmlserver/onca/xml3?". //should also still work with xml2 "$searchtype" .'='.urlencode($search) .'&'. 'dev-t' .'='.$dev_token .'&'. 'f' .'='.'xml' .'&'. 'locale' .'='.$locale .'&'. 'mode' .'='.$mode .'&'. 'page' .'='.$page .'&'. 't' .'='.$Aassociates_id[$locale].'&'. 'type' .'='.$type ; //Please note that: //- xml3 is the pathname of the URL //- ? denotes the spot where the arguments start //- that all arguments consist of 'argument_name=value' and that I have put them in alphabetical order //- that '&' seperates the arguments //you can also add: //- page=1 for result entries 1..10 //- page=2 for result entries 11..20 //- etc. //Each query result will contain only up to 10 entries. If you want to show more than 10 results, you will have to show several pages with results until you get a result with 0..9 entries, but when it's 0 you'll get an error message instead. //To search for ASIN's, replace the KeywordSearch line by AsinSearch=, upto 30 for lite and 10 for heavy searches. //To search for UPC's use instead: UpcSearch=,. //You can also use: //- AuthorSearch =.. (only for mode=books) //- ArtistSearch =.. (only for mode=music,classical) //- ActorSearch =.. (only for mode=dvd,vhs,video) //- DirectorSearch =.. (only for mode=dvd,vhs,video) //- ManufacturerSearch=.. (only for mode=electronics,kitchen,videogames,software,photo,pc-hardware) //- SimilaratiesSearch=ASIN (no mode) //Amazon lists (in the lite version) per book a record like: //
// 039480001X // The Cat in the Hat // Book // // Seuss // Theodor Seuss Geisel // Dr. Seuss // // June, 1957 // Random House (Merchandising) // http://images.amazon.com/images/P/039480001X.01.THUMBZZZ.jpg // http://images.amazon.com/images/P/039480001X.01.MZZZZZZZ.jpg // http://images.amazon.com/images/P/039480001X.01.LZZZZZZZ.jpg // $8.99 // $8.99 // $0.50 //
// //in case there was an error or nothing was found Amazon will return something like: //There are no exact matches for the search. if ($show_url) { //change this to true, if you want to see the exact search URL printed echo "
\n"; echo "Debugging:
\n"; echo "Asking Amazon's XML interface for:
\n"; echo $file."
\n"; echo "
\n"; } //do you want to use caching? $cache_time=3600; //in seconds how long a cache entry may be used //Use 0 for no caching or don't make a cache directory //Amazon has a maximum of one day for most data, //but one hour for prices unfortunately, I think //if you want to cache make a subdirectory called cache //and make sure Apache/PHP can write into it. Under Unix: chmod a+w cache $time0=time(); //ask the current time $cache='cache/'; //directory where to cache things //should we cache? $f_cache=($cache_time && is_dir ($cache) && is_readable($cache) && is_writable($cache)); //first we are cleaning out the cache if ($f_cache and $hd=opendir($cache)) { while ($fn=readdir($hd)) { if ($time0-filemtime($cache.$fn)>=$cache_time) { //is the file too old? if (!($fn=='.' or $fn=='..')) unlink($cache.$fn); //remove it } } closedir($hd); } //this is the actual program, it does: //- send the request using fopen() //- read the returned data into an XML string //- convert the XML string into an array //- print the array $cache_file_name=$cache.md5($file); //determine the name of the cache file if ($f_cache and //are we caching? is_readable($cache_file_name) and //file already readable in cache? $hf=fopen($cache_file_name,'r')) { //can it be opened? $A=unserialize(fread($hf,filesize($cache_file_name))); fclose($hf); } else { $mtime1=getmicrotime(); //time before Amazon if ($hf=fopen($file,'r')) { //else open the file from Amazon for ($sfile='';$buf=fread($hf,1024);) { //read the complete file (binary safe) 20040715: $sfile='' added $sfile.=$buf; } fclose($hf); $mtime2=getmicrotime(); //time after Amazon if ($show_xml) { //print the raw XML? echo "
\n";
      echo   htmlentities($sfile);          //print the file
      echo "
\n"; echo "
\n"; } $A=xml2array(utf8_decode($sfile)); //interpret the XML if ($f_cache and !($A['ErrorMsg'] or $A['ProductInfo']['ErrorMsg'])) { if ($hf=fopen($cache_file_name,'w')) { fwrite($hf,serialize($A)."\n"); fclose($hf); } } } else die(xu("can't get data from Amazon").".
\n"); } echo "

".xu('searching for')." '$search'

"; //you can change the h2's to h1's //now print the stuff if ($A) { //echo "Searchtype is '$searchtype'
\n"; //echo "

\n"; if ($show_array) { //show the array? print_array($A); //show the complete array } if ($e=$error_msg) { switch ($Aerror[$e]) { case 'print': echo "$e
\n"; break; default: echo xu('Amazon returned the error').': '.$e."
\n"; echo "
\n"; echo xu('please add this error message to the '). "". xl('database').".
\n"; break; } } else { switch ($searchtype) { case 'BlendedSearch': foreach ($A['BlendedSearch']['ProductLine'] as $d) { echo "


".xu('category' ).": ".$d['Mode' ]."
\n"; echo "".xu('relevance').": ".$d['RelevanceRank']."
\n"; print_mode($d); } break; default: echo "
\n"; print_mode($A); break; } } } function print_mode($A) { global $page; global $language; global $locale; global $mode; global $page; global $search; global $searchtype; $np=$A['ProductInfo']['TotalResults']; echo ''.xu('number of products').": $np
\n"; echo ''.xu('page').' '.($page).' '.xl('of').' '.(int)(($np+9)/10)."
\n"; echo "

\n"; echo "\n"; if (is_array($D=$A['ProductInfo']['Details']) and $D[0]) { foreach ($D as $i => $E) { printProduct($E); } } else { printProduct($D); } echo "
\n"; //provide links to previous and next page if ($searchtype=='BlendedSearch') { echo "".xu('search within this category')."\n"; } else { if ($np>10) { //echo "
\n"; echo "\n"; } } } if ($f_user_search) { //the next section adds a search box for the users echo "
\n"; echo "
\n"; //echo "\n"; //echo "\n"; //print " Search type
\n"; echo ""; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo ""; echo ""; echo "\n"; echo "\n"; echo "
".xu('product category:')."
".xu('search type:')."
".xu('which server:')."
".xu('language for page:')."
".xu('search string:')."
"; echo "\n"; echo "
\n"; //end of the search box section } //convert an XML-string to an array function xml2array($s) { if ($Atmp1=explode('>',$s,2) and ereg('^<\?(xml .*)\?$',$Atmp1[0],$Atmp2)) { $A['xml']=$Atmp2[1]; xml2array_sub($A,$Atmp1[1]); } return $A; } function xml2array_sub(&$A,$s) { global $error_msg; for ($c=0;ereg('<([^<>/ ]*)( [^<>]*)?/>(.*)',$s,$Atmp1) or ereg('<([^<>/ ]*)( [^<>]*)?>(.*)',$s,$Atmp1) and $Atmp2=explode('',$Atmp1[3],2);++$c) { $E=array(); $tag=$Atmp1[1]; if ($Atmp1[2]) { $Atmp3=explode(' ',substr($Atmp1[2],1)); foreach ($Atmp3 as $d) { $Atmp4=explode('=',$d,2); $Atmp4[1]=ereg_replace('^"(.*)"$','\1',$Atmp4[1]); $E[$Atmp4[0]]=$Atmp4[1]; } } if ($Atmp2) { if (!xml2array_sub($E,$Atmp2[0])) { $E=$Atmp2[0]; } $s=$Atmp2[1]; //rest of the xml-code $Atmp2=false; } else { $s=$Atmp1[3]; //rest of the xml-code } if (isset($A[$tag])) { //does it already exist? 20040715: isset() added if (!is_array($A[$tag]) or !$A[$tag][0]) { //not already a numberically indexed array? $Atag=$A[$tag]; //remove element again unset($A[$tag]); $A[$tag][]=$Atag; //make old element first element of it's former self } if ($E) { $A[$tag][]=$E; //add new element } } else { if ($E) { $A[$tag]=$E; //put it in the array under it's tag name if ($tag=='ErrorMsg') $error_msg=$E; //make this a global error message, because it can be anywhere in the XML code } } } return $c; } //print one Amazon product function printProduct($E) { global $Aassociates_id; global $dev_token; global $f_rich; //do you want 15% or 5%? (only for discounted books) global $locale; global $mode; global $norserver; if ($E) { //rebuild the URL if you want 15% instead of 5%: $url=($f_rich /*and $mode=='books' and $locale=='us'*/)?"$norserver/exec/obidos/ASIN/".$E['Asin'].'/ref=nosim/'.$Aassociates_id[$locale].'?dev-t='.$dev_token:$E['url']; echo ""; if ($d=$E['ImageUrlMedium']) { //$d=utf8_decode($d); echo ""; echo ""; echo ""; } echo ""; if ($d=$E['ProductName']) { //$d=utf8_decode($d); echo "$d
"; } if (is_array($dd=$E['Authors']['Author'])) { echo xl('by').": "; foreach ($dd as $i=>$d) { //$d=utf8_decode($d); if ($i) print ', '; //echo "$d"; } echo '
'; } else if ($d=$dd) { //$d=utf8_decode($d); echo xl('by').": "; echo "$d
"; } $dm=$E['Manufacturer']; $dr=$E['ReleaseDate' ]; if ($d=$E['Manufacturer']) { //$d=utf8_decode($d); echo xl('publisher').": $d"; } if ($dm and $dr) print ', '; if ($d=$E['ReleaseDate']) { //$d=utf8_decode($d); echo xl('released').": $d"; } if ($dm or $dr) print '
'; if ($d=$E['Isbn']) { echo "ISBN: $d
"; } $da=$E['Reviews']['AvgCustomerRating']; $ds=$E['SalesRank']; if ($ds) { echo xl('sales rank').": $ds, "; } if ($d and $ds) print ", "; if ($da) { echo xl('customer rating').": ".(($da-1)*25)."%"; } if ($da or $ds) print '
'; echo xl('price').": "; $do=$E['OurPrice' ]; $du=$E['UsedPrice']; if ($d=$E['OurPrice']) { //$d=utf8_decode($d); echo "$d (".xl('new').")"; } if ($do and $du) print ', '; if ($d=$E['UsedPrice']) { //$d=utf8_decode($d); echo "$d (".xl('used').")"; } if ($do or $du) echo '
'; echo ""; echo "\n"; } } function print_array($A) { echo "\n"; foreach ($A as $ky=>$da) { echo "\n"; } echo "
$ky"; if (is_array($da)) print_array($da); else { echo "
";
      echo htmlentities($da);
      echo "
"; } echo "
\n"; } $mtime3=getmicrotime(); //time at end function getmicrotime() { list($us,$s)=explode(' ',microtime()); return (float)$us+(float)$s; } //The next part is to check if the script isn't overburdoning your server. You can remove it if you like. echo "
\n"; $mtime_ama =$mtime2-$mtime1; //amazon time $mtime_local=$mtime3-$mtime0-$mtime4; //total time minus amazon time printf("Time used: %.2f s waiting for data from Amazon and %.2f s handling the data.
\n",$mtime_ama,$mtime_local); ?>