Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.06.01;
Скачать: CL | DM;

Вниз

Коллеги, поможите чем можете :)   Найти похожие ветки 

 
Ega23 ©   (2008-04-15 16:57) [0]

смысл такой: требуется парсер параметров, что передаются веб-серверу через Get или Post методы. Желательно на паскале, хотя можно и на С или PHP. Ну или ссылку, где эти правила детально описаны (сам "с ходу" не нашёл :( ).
В принципе, там после нескольких экспериментов более-менее понятно, как строки передаются, и самому написать не сильно сложно, но поскольку в веб-программировании я новичок, то тупо могу каких-то нюансов не учесть.


 
antonn ©   (2008-04-15 17:01) [1]

в каком смысле парсер?
print_r($_POST); выведет все элементы, перебор их:
foreach ($_POST as $key => $content){
//$key - ключ
echo($_POST[$key]);// выведет $content
}


 
БарЛог ©   (2008-04-15 17:02) [2]

для
http://delphimaster.net/view/15-1208264263/

принимаешь
$id=
$n=

Вроде как-то так, если память не изменяет. Точно не уверен - не проверял.


 
antonn ©   (2008-04-15 17:03) [3]

get запросы хранятся в массиве $_GET, post в $_POST.
не пойму вопроса :)


 
DVM ©   (2008-04-15 17:03) [4]


> смысл такой: требуется парсер параметров, что передаются
> веб-серверу через Get или Post методы.

только текстовых параметров? Там и файлы ведь могут быть.


 
antonn ©   (2008-04-15 17:04) [5]


> принимаешь
> $id=
> $n=

неправильно, нафиг regystry_globals :)
для http://delphimaster.net/view/15-1208264263/
$_GET["id"] будет равен 1208264263
$_GET["n"] будет равен 3
проверка на существование - isset($_GET["n"]), присутсвует регистрозависимость :)


 
wicked ©   (2008-04-15 17:04) [6]

на PHP это делается очень просто (без проверки на ошибки)
$params1 = explode("&", $param_string);
$params2 = array();
foreach($params1 as $line){
   list($key, $value) = explode("=", $line);
   params2[urldecode($key)] = urldecode($value);
}

(не учитывая, что за тебя это уже сделал веб-сервер)
но вряд ли тебе это поможет - в делфи нету explode

а ежели с проверкой на ошибки - то лучше юзать автоматы (КА) и перебирать по символу


 
antonn ©   (2008-04-15 17:10) [7]


> на PHP это делается очень просто (без проверки на ошибки)

ужась :) на php есть уже готовые пропарсенные массивы :)


 
wicked ©   (2008-04-15 17:12) [8]


>
> ужась :) на php есть уже готовые пропарсенные массивы :)

ужась у вас, поскольку вы не читаете, чего хочет автор...

а автор хочет парсер гетов-постов на паскале.... я и привел принцип разбора, но на пхп

зато теперь я знаю, по какому принципу набирают в супорт хостерам }:->


 
tesseract ©   (2008-04-15 17:13) [9]


> где эти правила детально описаны (сам "с ходу" не нашёл
> :( ).


Google+regexp + Delphi. Или сам конечноый автомат катай, но я думаю будет лень.


 
БарЛог ©   (2008-04-15 17:14) [10]

antonn ©   (15.04.08 17:04) [5]

> неправильно, нафиг regystry_globals :)
Я уже догадался :)


 
antonn ©   (2008-04-15 17:17) [11]


> wicked ©   (15.04.08 17:12) [8]

я просто не понял, зачем показывать аналог парсера на языке, где уже все сделано %)


 
Оригинал   (2008-04-15 17:20) [12]

const
 CR = CHR(13)+CHR(10);
 BufSize = 4096;

function GetMethod: String;
var
 buf: PChar;
begin
 GetMem(buf,BufSize);
 GetEnvironmentVariable(PChar("REQUEST_METHOD"),Buf,BufSize);
 Result := String(buf);
 FreeMem(buf);
end;

...

 if GetMethod = "POST"
   then Str := GetPostEnv
   else Str := GetGetEnv;

function ParamByName(inParams: String;Name: String): String;
var
 ss,st: String;
 k: Integer;
begin
 Result := "";
 ss := InParams;
 while Length(ss)>0 do
 begin
   k := Pos("&",ss);
   if k>0 then
   begin
     st := Copy(ss,1,k-1);
     ss := Copy(ss,k+1,10000);
   end
   else
   begin
     st := ss;
     ss := "";
   end;
   k := Pos("=",st);
   if K>0 then
   begin
     if Name=Copy(st,1,k-1) then
     begin
       Result := Decode(Copy(st,k+1,6000));
     end;
   end;
 end;

end;

function Decode(Value: String):String;
var
 i,L: Integer;
begin
 Result := "";
 L := 0;
 for i := 1 to Length(Value) do
 begin
   if (Value[i]<>"%") and (Value[i]<>"+") and (L<1) then
   begin
     Result := Result + Value[i];
   end
   else
   begin
     if Value[i]="+" then Result := Result+" "
     else if Value[i]="%" then
     begin
       L := 2;
       if (i<Length(Value)-1) then
       begin
         Result := Result + Chr(StrToInt("$"+Copy(Value,i+1,2))); //Chr(HexToInt(Value[i+1])*16+HexToInt(Value[i+2]));
       end;
     end
     else Dec(L);
   end;
 end;
end;

function GetGetEnv: String;
var
 buf: PChar;

begin
 GetMem(buf,BufSize);
 GetEnvironmentVariable(PChar("QUERY_STRING"),Buf,BufSize);
 Result := String(buf);
 FreeMem(buf);
end;

function GetPostEnv: String;
var
   StdIn,Size,Actual: Cardinal;
begin
 Result := "";
 StdIn := GetStdHandle(STD_INPUT_HANDLE);
 Size := SetFilePointer(StdIn,0,nil,FILE_END);
 SetFilePointer(StdIn,0,nil,FILE_BEGIN);
 SetLength(Result,Size);
 if Size>0 then
 begin
   ReadFile(StdIn,Result[1],Size,Actual,nil);
 end;

end;


 
DVM ©   (2008-04-15 17:20) [13]


> я просто не понял, зачем показывать аналог парсера на языке,
>  где уже все сделано

Чтобы понять как сделать на делфи или как вообще это делается очевидно. Хотя [6] на делфи все одно не портируешь в лоб.


 
Оригинал   (2008-04-15 17:23) [14]

Вдогонку пример получения значения параметра:

 for i := Low(tCommand) to High(tCommand) do
 begin
   if ParamByName(Str,"typedocau")= tCommand[i] then isTrue := True;
 end;


 
Ega23 ©   (2008-04-15 17:28) [15]

Сорри, тут разговор был.
поясняю: парсер нужен для FastCGI-программы. всё, что приходит через GET - имеем в QUERY_STRING. Всё, что приходит через POST - в fastcgi-аналоге stdin.
Понятно, что всё суть "parameter1=value1&parameter2=value2" и т.д.
Просто там ещё всякие спец-символы и т.п.
Вот технологию передачи спец-символов я так до конца и не понял.
Если есть где описание - ткните носом, сам парсер напишу. Просто в OpenSource-коды лезть крайне не хочется...  :)


 
Kolan ©   (2008-04-15 17:31) [16]

>
> Google+regexp + Delphi. Или сам конечноый автомат катай,
> но я думаю будет лень.

Я тоже хотел сначала написать, но, имхо, Ega и так про это знает. Он само выражения написать незнает как правильно.


 
DVM ©   (2008-04-15 17:32) [17]


> Если есть где описание - ткните носом, сам парсер напишу

RFC 1945  сам просил :)


 
Ega23 ©   (2008-04-15 17:34) [18]

Опытным путём вижу следующее:
есть строка Input Buffer: auth=1&login=%25%25%25&pwd=%25%3D%25%3D
Сначала пройти по строке разбить на пары по "&". Потом каждую пару разбить на сочетания параметр-значение по "="
Потом найти все сочетания "%__", заменить их на символ Chr(__) с учётом того, что они в Hex.


 
tesseract ©   (2008-04-15 17:39) [19]


> Опытным путём вижу следующее:


Ну в общем так и есть. Изредка возможно коррективы.


 
Оригинал   (2008-04-15 17:43) [20]


> Ega23 ©   (15.04.08 17:28) [15]
> Сорри, тут разговор был.
> поясняю: парсер нужен для FastCGI-программы. всё, что приходит
> через GET - имеем в QUERY_STRING. Всё, что приходит через
> POST - в fastcgi-аналоге stdin.
> Понятно, что всё суть "parameter1=value1¶meter2=value2"
> и т.д.
> Просто там ещё всякие спец-символы и т.п.
> Вот технологию передачи спец-символов я так до конца и не
> понял.
> Если есть где описание - ткните носом, сам парсер напишу.
>  Просто в OpenSource-коды лезть крайне не хочется...  :)


А какая разница - CGI или FASTCGI при передаче параметров клиентом?

Получение типа запроса:
function GetMethod: String;

Получение строки с запросом в зависимости от типа запроса(GET,POST):
function GetGetEnv: String;
function GetPostGetEnv: String;


Получение значения параметра из строки с запросом:
function ParamByName(inParams: String;Name: String): String;

Декодирование значения параметра в запросе:
function Decode(Value: String):String;


 
Ega23 ©   (2008-04-15 17:45) [21]


> Оригинал   (15.04.08 17:43) [20]


Я как раз сейчас твой код смотрю, правильно ли я всё понял.


 
Ega23 ©   (2008-04-15 17:46) [22]


> Ну в общем так и есть. Изредка возможно коррективы.


Вот не хотелось бы, чтобы "коррективы" всплыли в самый ненужный момент..  :)


 
Kolan ©   (2008-04-15 17:48) [23]


>
> Вот не хотелось бы, чтобы &laquo;коррективы&raquo; всплыли в самый ненужный
> момент&#133  :)

Надо прочитать стандарт на эту строку и полностью его реализовать.


 
palva ©   (2008-04-15 17:50) [24]


>
> Вот не хотелось бы, чтобы "коррективы" всплыли в самый ненужный
> момент..  :)
>

Плюсик заменяется на пробел.
Может быть, это не относится к FastCGI, не в курсе, что это такое.


 
Ega23 ©   (2008-04-15 17:51) [25]


> Надо прочитать стандарт на эту строку и полностью его реализовать.


5 баллов. А то я не понимаю... :)
Покажи стандарт, я ещё в [0] просил. Желательно оригинал, а не перевод.


 
Ega23 ©   (2008-04-15 17:53) [26]


> Оригинал   (15.04.08 17:43) [20]


Спасибо, код посмотрел, всё более-менее ясно.
Половину я уже и так написал, сейчас остальное добью.


 
Kolan ©   (2008-04-15 18:01) [27]

> Покажи стандарт

Я не уверен, но может:
http://ru.wikipedia.org/wiki/URI


 
Ega23 ©   (2008-04-15 18:06) [28]


> Я не уверен, но может:
> http://ru.wikipedia.org/wiki/URI


Спасибо, юникод я как раз и не учёл...  :)


 
palva ©   (2008-04-15 18:08) [29]

Если кодировка страницы UTF8, то русские символы в значениях будут состоять из двух байтов (два знака %)


 
Kolan ©   (2008-04-15 18:08) [30]

> Спасибо, юникод я как раз и не учёл&#133  :)

Прикалываешься? Или нет?

Вроде вот регулярка:
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?


 
Kolan ©   (2008-04-15 18:10) [31]

Мое имхо, что стандарт надо искать где-то на http://www.w3.org/


 
Мазут Береговой ©   (2008-04-15 18:12) [32]

http://www.scalabium.com/faq/dct0126.htm

http://www.delphidabbler.com/codesnip.php?action=named&routines=URLDecode&showsrc=1


 
palva ©   (2008-04-15 18:16) [33]

посмотреть
C:\Program Files\Borland\Delphi7\Source\Indy\IdURI.pas
там есть
   class function URLDecode(ASrc: string): string;
   class function URLEncode(const ASrc: string): string;
   class function ParamsEncode(const ASrc: string): string;
   class function PathEncode(const ASrc: string): string;


 
Ega23 ©   (2008-04-15 18:17) [34]

Всё, всем спасибо, дальше я сам.  :)


 
Fantasist..   (2008-04-15 19:47) [35]

Я когда-то в писал множество разнообразных парсеров. По мне так лучше сразу распарсить строку в ассоциативный массив параметров.Так можно и все параметры посмотреть и все имена и по имени параметр взять - удобнее в общем.
Заодно разбор может сразу указать, если строка содержит ошибки.


interface

TTokenType = (ttSpace,ttSymbol,ttWord,ttEOL,ttEOF);

TLexer = class
private
  fToken:string;
  fCur:PChar;
 
  function checkEOL:boolean;
public
 constructor Create(s:string);
 destructor Destroy; override;
 
 function next: TTokenType;
 property token:string read fToken;
end;

TURLParams = class
private
 fParams:THashMap;
 parser:TLexer;
 tokenType:TTokenType;

 procedure parse;
public
 constructor Create(s:string);
 params:THashMap read fParams;
end;

implementation

function isSpace(c:char):boolean;
begin
 result := (c=" ") or (c=9);
end;

function isLetterOrDigit(c:char):boolean;
begin
 result:= (c in ["0".."9"]) or (c in ["A".."Z"]) or (c in ["a".."z"])
end;

function isDigit(c:char):boolean;
begin
 result:=(c in ["0".."9"]);
end;

consturctor TLexer.Create(s:string)
begin
 fCur:=pointer(s);
end;

function TLexer.checkEOL:boolean;
begin
 result:=false;
 if fCur = 13 then
 begin
   inc(fCur);
   if fCur = 10 then
     inc(fCur);
   resut:=true;
 end
 else if fCur = 10 then
 begin
   inc(fCur);
   result:=true;
 end;
end;

function TLexer.next:TTokenType;
var
 ps:PChar;
begin
 if fCur = 0 then
 begin
   result:=ttEOF;
   exit;
 end;
 ps := fCur;
 if ckechEOL then
   result:=ttEOL
 else
 if isSpace(fCur) then
 begin
   while isSpace(fCur) then inc(fCur);
   result:=ttSpace;
 end
 else if isLetterOrDigit(fCur) then
 begin
   while isLetterOrDigit(fCur) then inc(fCur);
   result:=ttWord;
 end
 else  
 begin
   inc(fCur);
   result:=ttSymbol;
 end
 SetLength(fToken,Integer(fCur)-Integer(ps));
 move(ps^,pointer(fToken)^,Integer(fCur)-Integer(ps));
end;

constructor TURLParams.Create(s:string);
begin
 parser:=TLexer.Create(s);
 fParams:=THashMap.Create;
 parse;  
 parser.Free;
end;

function TURLParams.getDecoded:char;
begin
 result:="";
 tokenType:=parser.next;
 if (tokenType=ttWord) and (length(parser.token)=2) then
   result:=chr(StrToInt("$"+parser.token));
end;

function TURLParams.getParamName:string;
begin
 tokenType:=parser.next;
 if (tokenType <> ttWord) then ; //Error!!! (throw exception)
 result := parser.token;
end

function TURLParams.getParamValue:string;
begin
 result:="";
 tokenType:=parser.next;
 repeat
   case tokenType of
     ttWord: result:=result+parser.token;
     ttSymbol:
       case parser.token[1] of
         "+": result:=result+" ";
         "%": result:=result+getDecoded;
         "&":exit;
       else
         ; //Error or Ignore???
       end;
      ttSpace: ;//Error or Ignore???
    end;
 until (tokenType=ttEOF) or (tokenType = ttEOL);
end;

procedure TURLParams.parse
var
 paramName,paramValue:string;
begin
 repeat
    paramName := getParamName;
    parser.next;
    if (parser.token[i]<>"=") then ; //Error!!! (throw exception)
    paramValue:= getParamValue;
    fParams[paramName] = paramValue;    
 until (tokenType=ttEOF) or (tokenType = ttEOL);
end;


 Тут парочку вещей можно оптимизировать (например, getDecoded можно читать по символам и переводить в ручную, а не вызывать IntToStr; можно сделать лексеру способность чтения символа, когда токен состоит из одного символа, вместо того, чтобы копировать его в строку; строки можно не складывать плюсом, а дойти до конца выражения чтобы узнать длинну [тут заодно можно и getDecoded, оптимизировать как описанно выше] и скопировать строку целиком), немножко отладить, добавить нормальную обработку исключений и будет то что надо. :)
Да и омтимизация эта в данном случае скорее чисто для своего удовольствия - вряд ли реально на этом можно существенно сократить время выполнения.

 Вместо hash map можно тоже что-нибудь другое использовать. Map просто удобнее.


 
Fantasist..   (2008-04-15 19:50) [36]

Мда... Наверное это уже никому не нужно, но самому мне было приятно. Давно на Делфи ничего не писал, но как оказывается все само в памяти всплывает. :)


 
Ega23 ©   (2008-04-15 20:03) [37]


> Fantasist..   (15.04.08 19:47) [35]


ну я как раз приблизительно так и сделал.
Всё, вопрос снят, тему можно закрыть.
Всем спасибо!



Страницы: 1 вся ветка

Текущий архив: 2008.06.01;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.021 c
2-1210436683
Werewolf-Prankster
2008-05-10 20:24
2008.06.01
Ошибка: Undeclared Identifier


2-1210056270
Denis14312
2008-05-06 10:44
2008.06.01
Открытие базы DBF


2-1210594045
smartleds
2008-05-12 16:07
2008.06.01
Коллеги , подскажите как при выводе вместо запятой ,


15-1208316401
masv
2008-04-16 07:26
2008.06.01
доступ к нескольким сетям


2-1210226756
operator
2008-05-08 10:05
2008.06.01
Экспорт delphi кода с сохранением форматирования в word/html