Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2008.06.01;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.05 c
2-1209808931
assassin8899
2008-05-03 14:02
2008.06.01
автодобавление


2-1210058039
DevilDevil
2008-05-06 11:13
2008.06.01
Bitmap. Mask. не отображается.


8-1180605691
First
2007-05-31 14:01
2008.06.01
MP3 проигрыватель


3-1198824417
ivanovv
2007-12-28 09:46
2008.06.01
Как работать с файлом *.mdb, где названия полей в кириллице


15-1208766163
dreamse
2008-04-21 12:22
2008.06.01
Отличия С# от Delphi ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский