Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  05:17[Войти] | [Зарегистрироваться]
Ответ на вопрос № 60859

01-04-2008 16:00
Добрый вечер! Пытаюсь сделать свои функции URLDecode и URLEncode - использование idURI из Indy 10 прибавляет 50Кб к конечному файлу.
Взял эти функции из idURI.pas и осталось:

function URLDecode(ASrc: string): string;
var
  i: integer;
  ESC: string[2];
  CharCode: integer;
begin
  Result := '';    {Do not Localize}
  i := 1;
  while i <= Length(ASrc) do begin
    if ASrc[i] <> '%' then begin  {do not localize}
      Result := Result + ASrc[i]
    end else begin
      Inc(i); // skip the % char
      ESC := Copy(ASrc, i, 2); // Copy the escape code
      Inc(i, 1); // Then skip it.
      try
        CharCode := StrToInt('$' + ESC);  {do not localize}
        Result := Result + Char(CharCode);
      except end;
    end;
    Inc(i);
  end;
end;

function CharIsInSet(const AString: string; const ACharPos: Integer; const ASet:  String): Boolean;
begin
  if ACharPos > Length(AString) then begin
    Result := False;
  end else begin
    Result := Pos(AString[ACharPos], ASet)>0;
  end;
end;

function CharRange(const AMin, AMax : Char): String;
var i : Char;
begin
  Result := '';
  for i := Amin to AMax do
  begin
    Result := Result + i;
  end;
end;

function ParamsEncode(const ASrc: string): string;
var
  i: Integer;
const
  UnsafeChars = '*#%<> []'{do not localize}
begin
  Result := '';    {Do not Localize}
  for i := 1 to Length(ASrc) do
  begin
    if ((CharIsInSet(ASrc, i, UnsafeChars)) or (not (CharIsInSet(ASrc, i, CharRange(#33,#128))))) then
    begin {do not localize}
      Result := Result + '%' + IntToHex(Ord(ASrc[i]), 2);  {do not localize} // (1)
    end
    else
    begin
      Result := Result + ASrc[i];
    end;
  end;
end;

class function PathEncode(const ASrc: string): string;
const
  UnsafeChars = '*#%<>+ []'{do not localize}
var
  i: Integer;
begin
  Result := '';    {Do not Localize}
  for i := 1 to Length(ASrc) do begin
    if (CharIsInSet(ASrc, i, UnsafeChars)) or (ASrc[i] >= #$80) or (ASrc[i] < #32) then begin
      Result := Result + '%' + IntToHex(Ord(ASrc[i]), 2);  {do not localize}
    end else begin
      Result := Result + ASrc[i];
    end;
  end;
end;

function URLEncode(const ASrc: string): string;
var i: Integer;
begin
  Result := '';
  try
    i := LastDelimiter('/', ASrc);
    Result := PathEncode(Copy(ASrc, 0, i) + ParamsEncode(Copy(ASrc, i+1, Length(ASrc)-i)));
  finally
  end;
end;


Функции Sys.IntToHex, Sys.IntToStr, IndyPos заменил на IntToHex, IntToStr, Pos. Вроде определения этих функций не отличаются от стандартных.
Но, строка (1) выдает все русские символы не как %NN, а с каким-то непонятным префиксом %D1. Русская "р" конвертируется вообще непонятно во что.
В чем моя ошибка?

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

02-07-2008 15:07
Товарищи, написал следующий код для URLEncode (точнее - взял чужой и несколько изменил/дополнил).
Надеюсь, Вы сможете его проверить -

function ParamsEncode(const AStr: String): String;
const
  NoConversion = ['0'..'9','A'..'Z','a'..'z'];
var
  Sp, Rp: PChar;
  ParmName: Boolean;
begin
  SetLength(Result, Length(AStr) * 3);
  Sp := PChar(AStr);
  Rp := PChar(Result);
  ParmName := False;
  while Sp^ <> #0 do
  begin
    if (Sp^ = '?') or (Sp^ = '&') and (ParmName = false) then
      ParmName := true;
    if (Sp^ = '=') and (ParmName = true) then
    begin
      Rp^ := Sp^;
      Inc(Rp);
      Inc(Sp);
      ParmName := false;
    end;

    if ParmName or (Sp^ in NoConversion) then
      Rp^ := Sp^
    else
    begin
      FormatBuf(Rp^, 3, '%%%.2x', 6, [Ord(Sp^)]);
      Inc(Rp,2);
    end;

    Inc(Rp);
    Inc(Sp);
  end;
  SetLength(Result, Rp - PChar(Result));
end;


function URLEncode(const ASrc: string): string;
var i: Integer;
begin
  Result := '';
  try
    i := Pos('?', ASrc)-1;
    if i>0 then
      Result := Copy(ASrc, 0, i) + ParamsEncode(Copy(ASrc, i+1, Length(ASrc)-i))
    else
      Result := ASrc;
  finally
  end;
end;


06-05-2008 13:31 | Комментарий к предыдущим ответам
>>> код, что я привел в примере, - и есть код реализации этого метода из исходников indy
Прниошу свои извинения - посмотреть поленился....

04-05-2008 13:56 | Сообщение от автора вопроса
Python,
спасибо огромное! про метод в indy я, естественно, знаю (код, что я привел в примере, - и есть код реализации этого метода из исходников indy). try - из оригинального кода.

02-05-2008 12:33 | Комментарий к предыдущим ответам
Кстати, для Indy есть и штатный метод работы с URLEncode. Его формат: AURLString := TIdURI.URLEncode(AString); Но я им никогда не пользовался. Когда писал »вопрос КС №38145« сделал свою реализацию, а потом, когда узнал про штатный метод, на него переходить так и не стал. Но считаю нужным оповестить Вас о существовании такого метода.

30-04-2008 13:30
>>> а как правильно?
Ну на правильность не претендую, но примерно так:

function MyURLEncode(const S:string):string;
Const UnsafeChars=[#0..#32,'*','#','%','<','>','[',']',#128..#255];
      HexChar='0123456789ABCDEF';
var I,J:integer;
begin
  SetLength(Result,3*Length(S)); // maximal possible length
  J:=1;For I:=1 to Length(S) do
    if S[I] in UnsafeChars then begin
      Result[J]:='%';
      Result[J+1]:=HexChar[succ(ord(S[I])shr 4)];
      Result[J+2]:=HexChar[succ(ord(S[I])and $F)];
      Inc(J,3);
    end else begin Result[J]:=S[I];Inc(J);end;
  SetLength(Result,pred(J));
end;

function MyURLDecode(const S:string):string;
const HexChar='0123456789ABCDEF';
var I,J:integer;
begin
  SetLength(Result,Length(S));
  I:=1;J:=1;while(I<=Length(S)) do begin
    if(S[I]='%')and(I+2<Length(S))then begin // here you must check, that 2 characters left
      Result[J]:=chr(((pred(Pos(S[I+1],HexChar)))shl 4)or(pred(Pos(S[I+2],HexChar))));
      Inc(I,2);
    end else Result[J]:=S[I];
    Inc(I);
    Inc(J);
  end;
  SetLength(Result,pred(J));
end;


Пример использования:

procedure TForm1.Button1Click(Sender: TObject);
var S:string;
begin
  S:='Превед, медвед!!! Hello, bear!!!';
  ShowMessage(S);
  S:=MyURLEncode(S);
  ShowMessage(S);
  S:=MyURLDecode(S);
  ShowMessage(S);
end;


Ну и наконец, непонятно, что же там у Вас за try...finally - код внутри исключений не вызывает.

25-04-2008 11:18
>>> Файлу какого размера?
~500Кб.

>>> А вы в курсе, что каждое Result:=Result+... приводит к перераспределению памяти, что очень медленно?
а как правильно?

>>> И почему бы не почитать исходники - Indy ведь поставляется в исходниках, разве не так?
так этот код (слегка измененный) и есть из исходников Indy. вопрос в том, что я неправильно изменил.
кстати Result:=Result+... в исходниках Indy и есть

24-04-2008 13:59
>>> idURI из Indy 10 прибавляет 50Кб к конечному файлу
Файлу какого размера? Если отправлять файл на 10 байт - те же 50 килобайт пришиваются, или все-таки меньше? А вы в курсе, что каждое Result:=Result+... приводит к перераспределению памяти, что очень медленно? И почему бы не почитать исходники - Indy ведь поставляется в исходниках, разве не так?

03-04-2008 04:44 | Сообщение от автора вопроса
Господа, подскажите, пожалуйста, где же моя ошибка.
Аналогичный код в indy работает верно.
Почему строка

Result := Result + '%' + IntToHex(Ord(ASrc[i]), 2);


возвращает значение вида %D1nn, а не %nn? Откуда берется D1?

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Два кольца, два конца, посередине гвоздик.
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования