It's nasty and dirty. You've got to post back all those hidden fields...whatever they may be. In this application they are the same for every page: EVENTVALIDATION, VIEWSTATE, and of course the EVENTARGUMENT and EVENTTARGET fields:
//$d is the HTML source I've read from Page$1
$regexp1 = '%name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="[/a-zA-Z0-9+=]{1,1000}"%';
$regexp2 = '%name="__VIEWSTATE" id="__VIEWSTATE" value="[/a-zA-Z0-9+=]{1,50000}"%';
preg_match($regexp1, $d, $eventvalidation);
preg_match($regexp2, $d, $viewstate);
$out = explode("value=",$eventvalidation[0]);
$evt_validation = trim($out[1],'"'); // like my nasty hacks? I should really get better with preg_match, eh?
$out = explode("value=",$viewstate[0]);
$view_state = trim($out[1],'"');
$evt_target = 'ctl00$ContentPlaceHolder1$gv_results';
$evt_argument = 'Page$'.++$curr_page;
So, for subsequent pages:
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
//ASP servers think they know everything; if you don't spoof a JS-enabled client they don't send all the hidden fields
curl_setopt($ch, CURLOPT_USERAGENT, ('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0'));
// set up the CURL POST STUFF HERE
curl_setopt($ch, CURLOPT_POST,1);
$poster_ray = array("__EVENTTARGET"=>"$evt_target","__EVENTARGUMENT"=>"$evt_argument",
"__EVENTVALIDATION"=>$evt_validation,"__VIEWSTATE"=>$view_state);
curl_setopt($ch, CURLOPT_POSTFIELDS,$poster_ray);
HTH,