Если (REQUEST_METHOD="GET") то Взять данные из переменной окружения QUERY_STRING Иначе Если (REQUEST_METHOD="POST") то Проанализировать переменную QUERY_STRING Получить длинну данных из CONTENT_LENGTH Если (CONTENT_LENGTH>0) то Считать CONTENT_LENGTH байт из sdtin как данные. Иначе Выдать сообщение об ошибке и выйти.
http://.../cgi-bin/guestbook.cgi?user=bob&rec=0В этом случае шлюзу гостевой книги (guestbook.cgi) сообщается два параметра user и rec, с помощью которых она может узнать "куда записывать" или "как обрабатывать" данные поступающие через поток ввода.
Считывание данных через поток sdtin должно осуществляться в динамическую память, или же во временный файл, если размер памяти ограничен или данные слишком велики для полного размещения в ОЗУ. С чем это связано ? Это связано с тем, что при использовании статичестких буферов может произойти его переполнение.
Пример:
char cgi_data[1000]; ... long content_length=atol(getenv("CONTENT_LENGTH")); fread(cgi_data,content_length,1,stdin); ...Надеюсь все сразу видно :-)). Если content_length>1000, то произойдет переполнение cgi_data. Переполнение буферов это излюбленный метод атаки хакеров. Вместо этого лучше выделять память динамически:
char *cgi_data; ... long content_length=atol(getenv("CONTENT_LENGTH")); cgi_data=(char *)malloc(content_length); if (cgi_data!=NULL) fread(cgi_data,content_length,1,stdin); ...После получения данных от сервера их надо еще декодировать. Можно это сделать сразу, а можно по мере надобности. Если Вы будете это делать сразу, то Вам также придется их разбить на куски, так как при декодировании могут появиться лишние знаки "&" и "=", которые больше не позволят вам отделять пары "имя=значение" друг от друга.
Вот пример процедуры, которая декодирует данные из буфера:
/* Возвращает верхний регистр символа*/ char upperchar(char ch) { if ((ch>='a') && (ch<='z')) { ch='A'+(ch - 'a'); return ch; } else return ch; }; /* Переводит из Hex в Dec*/ char gethex(char ch) { ch=upperchar(ch); if ((ch>='0')&&(ch<= '9')) return (ch-'0'); if ((ch>='A')&&( ch<='F')) return (ch-'A'+10); }; /* Ищет и возвращает параметр с именем name, в buffer. Если параметр name не найден, возвращает NULL. Пример : message = getparam(post_buffer,"message="); Замечание : символ "=" после имени параметра не удаляется и входит в возвращаемый результат, поэтому рекомендуется искать параметр вместе с символом "=". */ char *getparam(char *buffer,char *name) { if (buffer==NULL) return NULL; char *pos; long leng=512,i=0,j=0; char h1,h2,Hex; char *p=(char *)malloc(leng); pos=strstr(buffer,name); if (pos == NULL) return NULL; if ((pos!=buffer) && (*(pos-1)!='&')) return NULL; pos+=strlen(name); while ( (*(pos+i)!='&')&&( *(pos+i)!='\0' )) { if ( *(pos+i)=='%' ) { i++; h1=gethex(*(pos+i)); i++; h2=gethex(*(pos+i)); h1=h1<<4; *(p+j)=h1+h2; } else { if (*(pos+i)!='+') *(p+j)=*(pos+i); else *(p+j)=' '; }; i++; j++; if (j >= leng) p=(char*)realloc(p,leng+20); leng+=20; }; if (j < leng) p=(char*)realloc(p,j+1); *(p+j)='\0'; return p; };
Теперь используя функцию getparam Вы сможете в любое время получить какой-нибудь параметр. Конечно эта процедура еще далека от совершенства, так как использует стандартный realloc и не обрабатывает ошибку нехватки памяти, но всеже ее можно использовать для данных не особо больших размеров.
Кстати надо еще сказать, что нецелесообразно размещать поступающие данные размером >64 Кб. в памяти, если, например, скрипт предназначен для закачки файлов, то можно (а вернее нужно) напрямую организовать запись в файл, иначе файл размером в пару мегабайт ваш скрипт не обработает :-)).