Punycode-конвертер доменов (.рф)

Разбираем вопросы и проблемы при написанию скриптов. Обсуждения API интерфейса DataExpress и прочих вопросов связанных с программированием и кодингом.
Аватара пользователя
Владимир
Администратор
Сообщения: 614
Зарегистрирован: 10 фев 2018, 18:27
Откуда: Белгород
Контактная информация:

Punycode-конвертер доменов (.рф)

Сообщение Владимир » 04 окт 2019, 19:50

Может пригодиться для случаев, где необходимо выполнить запрос на "http://домен.рф", а используемый http-клиент не поддерживает преобразование кириллицы в соответсвующие "кракозябры".
Конвертирование выполняется в обе стороны (второй параметр: 1 - ToUnicode; 0 (или пустой) - ToASCII).

Пример:

Код: Выделить всё

debug(Punycode('http://россия.рф/?query=null',0)); 
// результат: http://xn--h1alffa9f.xn--p1ai/?query=null 
  
debug(Punycode('http://xn--h1alffa9f.xn--p1ai/?query=null',1)); 
// результат: http://россия.рф/?query=null

Код: Выделить всё

function Punycode(Url:widestring;Enc_Dec:variant):string;
  var JS:variant;
  Mode:string;
  Protocol,
  Domain,
  PUrl:string;
  PPos:integer;
begin
  if VarToStr(Enc_Dec)='1'
  then Mode:='ToUnicode'
  else Mode:='ToASCII';
  PUrl:=trim(Url);
  PPos:=Utf8Pos('://',Url,1);
  if PPos>0 then
  begin
    Protocol:=Utf8Copy(Url,1,PPos+2);
    Utf8Delete(PUrl,1,Utf8Length(Protocol));
  end;
  Domain := Utf8Copy(PUrl,1,Utf8Pos('/',PUrl,1)-1);
  Utf8Delete(PUrl,1,Utf8Length(Domain));
  try
    JS:=CreateOleObject('MSScriptControl.ScriptControl');
    JS.Language := 'JScript';
    JS.Reset;
    JS.AddCode(
'/*'+
'http://stackoverflow.com/questions/183485/can-anyone-recommend-a-good-free-ja'+
'vascript-for-punycode-to-unicode-conversion Javascript Punycode converter der'+
'ived from example in RFC3492. This implementation is created by some@domain.n'+
'ame and released into public domain'+
'*/'+
'var punycode=new function Punycode(){this.utf16={decode:function(q){var p=[],'+
'r=0,o=q.length,s,n;while(r<o){s=q.charCodeAt(r++);if((s&63488)===55296){n=q.c'+
'harCodeAt(r++);if(((s&64512)!==55296)||((n&64512)!==56320)){throw new RangeEr'+
'ror("UTF-16(decode): Illegal UTF-16 sequence")}s=((s&1023)<<10)+(n&1023)+6553'+
'6}p.push(s)}return p},encode:function(p){var o=[],q=0,n=p.length,r;while(q<n)'+
'{r=p[q++];if((r&63488)===55296){throw new RangeError("UTF-16(encode): Illegal'+
' UTF-16 value")}if(r>65535){r-=65536;o.push(String.fromCharCode(((r>>>10)&102'+
'3)|55296));r=56320|(r&1023)}o.push(String.fromCharCode(r))}return o.join("")}'+
'};var f=128;var k=72;var a="\x2D";var c=36;var e=700;var b=1;var g=26;var m=3'+
'8;var d=2147483647;function j(n){return n-48<10?n-22:n-65<26?n-65:n-97<26?n-9'+
'7:c}function l(o,n){return o+22+75*(o<26)-((n!=0)<<5)}function i(q,p,o){var n'+
';q=o?Math.floor(q/e):(q>>1);q+=Math.floor(q/p);for(n=0;q>(((c-b)*g)>>1);n+=c)'+
'{q=Math.floor(q/(c-b))}return Math.floor(n+(c-b+1)*q/(q+m))}function h(o,n){o'+
'-=(o-97<26)<<5;return o+((!n&&(o-65<26))<<5)}this.decode=function(v,q){var s='+
'[];var H=[];var B=v.length;var A,F,E,r,p,D,z,o,u,C,y,x,G;A=f;E=0;r=k;p=v.last'+
'IndexOf(a);if(p<0){p=0}for(D=0;D<p;++D){if(q){H[s.length]=(v.charCodeAt(D)-65'+
'<26)}if(v.charCodeAt(D)>=128){throw new RangeError("Illegal input >= 0x80")}s'+
'.push(v.charCodeAt(D))}for(z=p>0?p+1:0;z<B;){for(o=E,u=1,C=c;;C+=c){if(z>=B){'+
'throw RangeError("punycode_bad_input(1)")}y=j(v.charCodeAt(z++));if(y>=c){thr'+
'ow RangeError("punycode_bad_input(2)")}if(y>Math.floor((d-E)/u)){throw RangeE'+
'rror("punycode_overflow(1)")}E+=y*u;x=C<=r?b:C>=r+g?g:C-r;if(y<x){break}if(u>'+
'Math.floor(d/(c-x))){throw RangeError("punycode_overflow(2)")}u*=(c-x)}F=s.le'+
'ngth+1;r=i(E-o,F,o===0);if(Math.floor(E/F)>d-A){throw RangeError("punycode_ov'+
'erflow(3)")}A+=Math.floor(E/F);E%=F;if(q){H.splice(E,0,v.charCodeAt(z-1)-65<2'+
'6)}s.splice(E,0,A);E++}if(q){for(E=0,G=s.length;E<G;E++){if(H[E]){s[E]=(Strin'+
'g.fromCharCode(s[E]).toUpperCase()).charCodeAt(0)}}}return this.utf16.encode('+
's)};this.encode=function(C,o){var u,E,y,B,z,x,v,r,w,F,D,p;if(o){p=this.utf16.'+
'decode(C)}C=this.utf16.decode(C.toLowerCase());var A=C.length;if(o){for(x=0;x'+
'<A;x++){p[x]=C[x]!=p[x]}}var s=[];u=f;E=0;z=k;for(x=0;x<A;++x){if(C[x]<128){s'+
'.push(String.fromCharCode(p?h(C[x],p[x]):C[x]))}}y=B=s.length;if(B>0){s.push('+
'a)}while(y<A){for(v=d,x=0;x<A;++x){D=C[x];if(D>=u&&D<v){v=D}}if(v-u>Math.floo'+
'r((d-E)/(y+1))){throw RangeError("punycode_overflow (1)")}E+=(v-u)*(y+1);u=v;'+
'for(x=0;x<A;++x){D=C[x];if(D<u){if(++E>d){return Error("punycode_overflow(2)"'+
')}}if(D==u){for(r=E,w=c;;w+=c){F=w<=z?b:w>=z+g?g:w-z;if(r<F){break}s.push(Str'+
'ing.fromCharCode(l(F+(r-F)%(c-F),0)));r=Math.floor((r-F)/(c-F))}s.push(String'+
'.fromCharCode(l(r,o&&p[x]?1:0)));z=i(E,y+1,y==B);E=0;++y}}++E,++u}return s.jo'+
'in("")};this.ToASCII=function(r){var n=r.split(".");var o=[];for(var p=0;p<n.'+
'length;++p){var q=n[p];o.push(q.match(/[^A-Za-z0-9-]/)?"xn--"+punycode.encode'+
'(q):q)}return o.join(".")};this.ToUnicode=function(r){var n=r.split(".");var '+
'o=[];for(var p=0;p<n.length;++p){var q=n[p];o.push(q.match(/^xn--/)?punycode.'+
'decode(q.slice(4)):q)}return o.join(".")}}();'
    );
    result:= Protocol+JS.Eval('punycode.'+Mode+'("'+Domain+'");')+PUrl;
  except
    debug(ExceptionParam);
  finally
    Mode:=#0;
    Protocol:=#0;
    Domain:=#0;
    PUrl:=#0;
    PPos:=0;
    JS:=Unassigned;
    JS:=null;
  end;
end;

procedure dxButton1_On_Click(Sender: TObject);
begin
  debug(Punycode('https://россия.рф/?query=null',0));
  debug(Punycode('https://xn--h1alffa9f.xn--p1ai/?query=null',1));
end;


procedure Form_Create;
begin
  dxButton1.OnClick := @dxButton1_On_Click;
end;

Теги: