уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Не так давно я писал про единственную более менее готовую библиотеку OAuth для Delphi, которую хотел использовать в Twitter’e. Проблема её использования заключалась в том, что при отправке сообщений, содержащих русские символы возвращалась ошибка 401. Сегодня эта досадная ошибка была решена. В связи с чем выкладываю в доступ исправленную библиотеку OAuth для Delphi.

Прежде всего, следует указать автора этой библиотеки, т.к. я всего лишь немного доработал её, а не создал с нуля — вот ссылка на его блог. К сожалению, его проект по OAuth уже долгое время не развивается, но кое-какие исходники, при необходимости, вы сможете найти в блоге, в т.ч. и модуль для работы с Twitter’ом с использованием библиотеки.
Теперь, что касается исправлений. Ошибка заключалась в том, что при доступе к ресурсам Twitter’а неверно формировалась строка Base_String. По спецификации OAuth все символы в строке должны быть в кодировке URF-8 и при этом параметры URL (за исключением параметров OAuth) должны располагаться по алфавиту. Кодирование строки проводилось следующим образом:

base := 'POST&' + TOAuthUtil.urlEncodeRFC3986(URL) + '&' + UrlEncode(encodeParams(oParams,'&',false));

В encodeParams кодирование параметров проходило так:

buf := Params.Names[i] + '='+ UrlEncode(Utf8Encode(Params.ValueFromIndex[i])) + ''

Функция UrlEncode выглядит следующим образом:

function UrlEncode(const S : String) : String;
var
    I : Integer;
    Ch : Char;
begin
    Result := '';
    for I := 1 to Length(S) do begin
        Ch := S[I];
        if ((Ch >= '0') and (Ch <= '9')) or
           ((Ch >= 'a') and (Ch <= 'z')) or
           ((Ch >= 'A') and (Ch <= 'Z')) or
           (Ch = '.') or (Ch = '-') or (Ch = '_') or (Ch = '~')then
            Result := Result + Ch
        else
            Result := Result + '%' + IntToHex(Ord(Ch), 2);
    end;
end;

В результате при кодировании любого русского символа получалась следующая картина:
символ

П = %D0%9F

оказывался в Base String как:

%2541F%25440

А при отправке POST-запроса снова как

%D0%9F

В результате чего сервер и возвращал нам 401 ошибку.
Я немного видоизменил кодирование параметров в Base String и использовал вместо UrlEncode немного измененную функцию из Synapse — EncodeTriplet:

function EncodeTriplet(const Value: AnsiString; Delimiter: AnsiChar;
  Specials: TSpecials): AnsiString;
var
  n, l: Integer;
  s: AnsiString;
  c: AnsiChar;
begin
  SetLength(Result, Length(Value) * 3);
  l := 1;
  for n := 1 to Length(Value) do
  begin
    c := Value[n];
    if c in Specials then
    begin
      Result[l] := Delimiter;
      Inc(l);
      s := IntToHex(Ord(c), 2);
      Result[l] := s[1];
      Inc(l);
      Result[l] := s[2];
      Inc(l);
    end
    else
    begin
      Result[l] := c;
      Inc(l);
    end;
  end;
  Dec(l);
  SetLength(Result, l);
end;

Где TSpecials — множество:

type
  TSpecials = set of AnsiChar;
 
const
  URLSpecialChar: TSpecials =
  [#$00..#$20, '<', '>', '"', '%', '{', '}', '|', '\', '^', '~', '[', ']',
    '`', #$7F..#$FF];

Проверил работу библиотеки, отправив сообщения в Twitter, используя методы API update и direct_messages/new — сообщения отправились без проблем, в т.ч. и сообщения, содержащие в нике пользователя или в тексте спец. символы.
Теперь можете скачивать доработанную библиотеку, скачивать с блога автора модуль для Twitter’а и создавать свои приложения для Twitter в Delphi.
На всякий случай приведу ссылки, которые могу быть Вам полезны:
1. Репозиторий с первоначальным исходником библиотеки (не обновлялся более года)
2. Блог автора проекта OAuthDelphi
3. Пост в моем блоге по использованию библиотеки.

Скачать исходник: Исходники —> API онлайн-сервисов —> Прочие API
0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
15 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
trackback
progg.ru
20/05/2010 17:52

Twitter OAuth и русские символы. Решено. | Delphi в Internet…

Thank you for submitting this cool story — Trackback from progg.ru…

vitaly
30/05/2010 16:28

Не работает закачка с iFolder

дмитрий
04/03/2011 13:49

Перезалей пожалуйста на другой файлоообменник, невозможно скачать от сюда

Леха
Леха
18/03/2011 20:09

Привет, Влад!
Занялся тут написанием проги под твиттер. возник следющий вопрос. Взял твой модуль OAuth с кириллицей. Все хорошо, все работает (тебе, к стати спасибо за это). Одно «НО» не хочет восклицательный знак отправлять сразу «401» ошибка и хоть ты тресни… Не подскажешь, как можно эту проблему решить?

Леха
Леха
18/03/2011 20:11

Ах, да, чуть не забыл, я с Indy (может это важно) использую версию. Т.к. только недавно с Indy разобрался, и нет желания с новой библиотекой разбираться

Леха
Леха
18/03/2011 20:26

А, все, видно погорячился тревогу бить, добавил «?»,»!»,»#»,»@» (всЕ, которые не работали) в Specials все заработало.
Сорри за беспокойство!

ildvild
22/10/2012 00:55

Vlad, почему-то не отправляется символ #. Не подскажешь в чем может быть дело?

Леха
Леха
23/10/2012 12:07

ildild смотри мой предыдущий комент,
«А, все, видно погорячился тревогу бить, добавил «?»,»!»,»#»,»@» (всЕ, которые не работали) в Specials все заработало.
Сорри за беспокойство!»

ildvild
23/10/2012 19:23

Леха, а можешь скинуть свой Oauth.pas. Т.к. как я уже написал на форуме, если добавить эти символы в Specials именно в таком виде, то у меня ноль реакции(как не отправлялись так и не отправляются). Если же я добавляю их ASCII коды(напр #=#$23), то эти символы нормально отправляются, но перестают отправляться другие(напр ‘:’ или точка). Вообщем я хз почему так)

Alex Brann
23/05/2013 12:25

Можно ещё вот так переписать UrlEncode

function TForm1.UrlEncode(const S : String) : String;
var
i : integer;
u : ansistring;
r : ansistring;
begin
r := »;
u := ansistring(UTF8Encode(S));
for i := 1 to Length(u) do
begin
case u[i] of
‘A’..’Z’, ‘a’..’z’, ‘0’..’9′, ‘-‘, ‘_’, ‘.’:
r := r + u[i];
else
r := r + ‘%’ + ansistring(IntToHex(Ord(u[i]), 2));
end;
end;
Result := string(r);
end;

Alex Brann
23/05/2013 12:28

Можно ещё вот так переписать UrlEncode и русские буквы будут нормально отправляться

function UrlEncode(const S : String) : String;
var
i : integer;
u : ansistring;
r : ansistring;
begin
r := '';
u := ansistring(UTF8Encode(S));
for i := 1 to Length(u) do
begin
case u[i] of
'A'..'Z', 'a'..'z', '0'..'9', '-', '_', '.':
r := r + u[i];
else
r := r + '%' + ansistring(IntToHex(Ord(u[i]), 2));
end;
end;
Result := string(r);
end;

trackback

[…] Twitter OAuth и русские символы. Решено. | Delphi в Internet к записи OAuth, Twitter и русские символы. […]